Я узнаю о функциях высшего порядка из книги «Изучите Haskell во благо!» Миран Липовача. Я знаю, что функция flip принимает функцию и возвращает функцию, аналогичную исходной, но с перевернутыми первыми двумя аргументами.
Я не совсем понимаю, как работает следующий пример с функцией карты.
ghci> map (flip subtract 20) [1,2,3,4]
[19,18,17,16]
Map принимает функцию и применяет ее к каждому элементу списка, в результате чего получается новый список. Но поскольку флип — это функция, которую принимает карта, с параметрами subtract 20 [1,2,3,4], будет ли результирующая функция 20 subtract [1,2,3,4]?
Я не думаю, что это правильно, поскольку такое значение, как 19, создается только при вводе subtract 1 20. Я не уверен, как вычитание будет работать в приведенном выше примере для создания выходного списка.
Скобки важны — нельзя «разлагать» (flip subtract 20).





Нет, здесь функция 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]
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 применяется к каждому элементу списка с помощью функции карты.
But since flip is the function map takes...
Нет. 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проверка этой функции по заданному списку дает показанный результат.
По сути,
flipиногда не нужен, если вы можете использовать инфиксную запись функции. Например`subtract` 20. Так что можете делатьmap (`subtract` 20) [1,2,3,4]. Или лучшеmap ((-) 20) [1,2,3,4]