2014-11-02 4 views
0

У меня есть две функции, оба из которых возвращает список:Как написать оператор карты для сравнения каждого элемента из двух списков в haskell?

enter earth = head $ do 
    lst <- earth 
    return $ map (\x -> if (x == 0) then 2 else x) lst 

helper earth = head $ do 
    lst <- tail (earth) 
    return lst 

, где земля еще одна функция, которая возвращает список списков, как [[1,2,3], [2,3,4], [ 4,7,3]]. В вспомогательной функции я возвращаю второй элемент этого списка списков, т. Е. Головку хвоста. А в функции ввода только голова. Теперь я пишу еще одну функцию, и я хочу передать эти две функции в качестве аргументов. Я делаю это:

see :: [Int] -> [Int] -> [Int] 
see enter helper = return $ map (\ x y -> if (x == 2) && (y == 0) then 2 else y) enter helper 

Я в основном пытаюсь сделать, это проверить, если список возвращаемого ввести имеет 2 и второй список имеет нуль в этом месте, а затем изменить что 0 до 2 в противном случае пусть элемент во втором списке будет таким, какой он есть.

Что я здесь делаю неправильно?

EDIT:

Итак, есть функция земля возвращение как это: [[0,0,1], [1,0,1], [0,0,0]]. Функция ввода принимает головку земли (которая равна [0,0,1] и делает это следующим образом: [2,2,1]. Вспомогательная функция принимает и возвращает второй элемент (головка хвоста) список списков, возвращаемых землей (это [1,0,1]). Теперь функция see, принимает эти [2,2,1] и [1,0,1] как два аргумента, и если элемент 2 в первом списке и 0 во втором списке (т. Е. Из этого примера, второго элемента в обоих списках, тогда 0 должно стать 2 во втором списке, а то, что должно быть возвращено, должно быть примерно таким: [1, 2,1]

+1

Используйте функцию 'zip'? –

ответ

1

Похоже, что вы хотите что-то вроде этого:

 xs = [ ...,  1,  2,  0,  1, ... ] 
     ys = [ ...,  3,  0,  4,  0, ... ] 
zip xs ys = [ ..., (1,3), (2,0), (0,4), (1,0), ... ] 
    result = [ ...,  3,  2,  4,  0, ... ] 

result является список ys с нулями, замененными 2s, где есть a 2 в списке xs.

Таким образом, вы можете выразить эту логику в значительной степени непосредственно в списке понимание:

result = [ r | (x,y) <- zip xs ys, let r = if y == 0 && x == 2 then 2 else y ] 
+0

Итак, теперь я пишу что-то вроде этого: see = [r | (x, y) <- zip введите хелпер, пусть r = if y == 0 && x == 2 then 2 else y] Но я получаю ошибку типа. –

+0

'enter' и' helper' - это функции, а не списки. Если 'as' - это список, то' enter as' также является списком, поэтому вы хотите заменить 'xs'' enter as' и 'ys' на' helper bs' для некоторых выражений списка 'as' и' bs ' – ErikR

+0

Я проработал. Не могли бы вы сказать мне, могу ли я написать какие-то вложенные операторы if внутри понимания списка? Подобно списку, возвращаемому результатом, я хочу сделать некоторые вычисления для каждого элемента этого списка. Можно ли писать вложенные, если внутри этого списка понимается? –

2

zipWith это функция, которую вы ищете. map работает только в одном списке, в то время, так что ваше использование этого приведет к ошибке типа. Если вы просто замените map с zipWith в том, что последняя строка, она должна работать. Также вы должны удалить return. В контексте списка return только помещает что-то в одноэлементный список: return x = [x]. Обратите внимание: return является функцией и на самом деле не связан с return на языках с C-влиянием. Я бы также предложил не использовать do нотацию для списков на этом этапе.

Кроме того, последняя функция не использует две другие функции, даже если она использует эти имена. Я не уверен, что это то, чего вы хотите или нет. Это эквивалентно определению see, в котором вы использовали имена x и y вместо enter и helper.

Вот пример поведения zipWith:

λ> zipWith (*) [2, 3, 4] [10, 100, 1000] 
[20,300,4000] 
+0

Я не понимаю, что вы подразумеваете под этим, что моя последняя функция не требует ввода и вспомогательной функции. Он получает только два списка из этих функций, на которых он будет выполнять вычисления. : O –

+0

@EricaMaine О, я просто сказал, что эти аргументы не должны иметь то же имя, что и другие функции, но он будет работать в любом случае. С другой стороны, я имею в виду вместо того, чтобы использовать 'map' в функции' see', вы хотите использовать 'zipWith'. 'zipWith' имеет поведение, которое вы описываете, применив две функции аргумента в двух списках так, как вы хотите (см. ссылку на документацию luqui, добавленную в мой ответ для справки). –

+0

@EricaMaine Я добавил демонстрацию того, как работает 'zipWith'. Кроме того, похоже, что существует терминологическая проблема: «земля» - это список, а не функция (не то, что я ожидал сказать сегодня, ха-ха). –

1

map ходит только по 1 списку, но вы пытаетесь идти более 2 списков в то же время, и что-то вычислить.

Так что вам нужна функция, которая принимает функцию с 2-мя параметрами, 2 списка и возвращает список с тем же типом результата функции: (a -> b -> c) -> [a] -> [b] -> [c]

И hoogle находит функцию, которая обладает этим свойством: zipWith

Таким образом, вы написать вспомогательную функцию, которая делает то, что вы хотите:

helper 0 2 = 2 
helper _ y = y 

Теперь вы пишете функцию см и поставить вспомогательную функцию в предложении где (вы, вероятно, не нужно, что п соборование позже):

see a b = zipWith helper a b 
    where helper 2 0 = 2 
      helper _ y = y 

Я не знаю, почему вы используете do, но это не является необходимым здесь.

Смежные вопросы