Понимание функции карты, когда первый аргумент использует переворот - PullRequest
4 голосов
/ 08 июня 2019

Я узнаю о функциях высшего порядка из «Learn You a Haskell for Great Good!»Миран Липовака.Я знаю, что функция flip принимает функцию и возвращает функцию, аналогичную оригиналу, но с переворотом первых двух аргументов.

Я не до конца понимаю, как работает следующий пример с функцией map.

ghci> map (flip subtract 20) [1,2,3,4]
[19,18,17,16]

Карта берет функцию и применяет ее к каждому элементу списка, в результате чего создается новый список.Но поскольку flip - это функция, которую берет карта функций с параметрами subtract 20 [1,2,3,4], получится ли полученная функция 20 subtract [1,2,3,4]?

Я не думаю, что это правильно, поскольку значение, такое как 19, создается только при вводеsubtract 1 20.Я не уверен, как вычитание будет работать в приведенном выше примере для создания списка вывода.

Ответы [ 3 ]

8 голосов
/ 08 июня 2019

Нет, здесь функция map :: (a -> b) -> [a] -> [b] принимает значение (flip subtract 20), это параметр, который вы передаете map.Это означает, что:

map (flip subtract 20) [1,2,3,4]

эквивалентно:

[flip subtract 20 1, flip subtract 20 2, flip subtract 20 3, flip subtract 20 4]

flip :: (a -> b -> c) -> b -> a -> c - это функция, которая принимает функцию ипереворачивает параметры.Таким образом, flip subtract 20 семантически эквивалентен \x -> subtract x 20.Таким образом, наш список эквивалентен:

[subtract 1 20, subtract 2 20, subtract 3 20, subtract 4 20]

subtract :: Num a => a -> a -> a - это «перевернутая» версия (-), поэтому она эквивалентна:

[20 - 1, 20 - 2, 20 - 3, 20 - 4]

и, следовательно, эквивалентно:

Prelude> map (flip subtract 20) [1,2,3,4]
[19,18,17,16]

Более короткая версия приведенного выше выражения выглядит так:

map (20 -) [1,2,3,4]
3 голосов
/ 08 июня 2019

Но так как переворот - это функция, карта занимает ...

Нет.map принимает функцию в качестве первого параметра - здесь это flip subtract 20.Это действительно функция, как мы сейчас увидим (если бы это было не так, компилятор выдаст ошибку, потому что ожидает функцию здесь).

Мы начнем с вычитание - который фактически определяется как flip (-).Это означает, что flip subtract это просто (-), или:

flip subtract = \a b -> a - b

в отличие от

subtract = \a b -> b - a

Итак, путем каррирования:

flip subtract a = \b -> a - b

и заменыв 20:

flip subtract 20 = \b -> 20 - b

Так что flip subtract 20 действительно функция, которая возвращает результат вычитания аргумента из 20. map Пинг этой функции по указанному списку дает показанный результат.

3 голосов
/ 08 июня 2019

flip имеет следующую функциональность: она применяет данную функцию к двум заданным параметрам в обратном порядке («перевернуто»).

Prelude> :t flip
flip :: (a -> b -> c) -> b -> a -> c

Вот так (flip subtract 20) становится функцией f (x) = 20-x, где (subtract 20) соответствует g (x) = x-20.

Затем f применяется к каждому элементу списка с помощью функции карты.

...