Как работает функция флип?
Haskell новичок здесь. Я проходил через Учиться вам haskell, и натолкнулся на это определение функции флип.
flip' :: (a -> b -> c) -> (b -> a -> c)
flip' f = g
where g x y = f y x
Чего я не понимаю, откуда взялись х и у? Я имею в виду, что подпись говорит мне, что flip'
- это функция, которая принимает функцию (с двумя параметрами) и возвращает функцию (опять же с двумя параметрами).
Если я понимаю это право, когда пишу функцию, которая выглядит как
foo :: (a -> b) -> a -> b
foo f x = f x -- applies the function f on x
Но тогда в этом случае я передаю параметр явно [ie x
], и поэтому я могу получить к нему доступ в теле функции. Итак, как получилось, что функция flip'
может получить доступ к параметрам x и y?
Ответы
Ответ 1
Prelude, который находится в base на hackage.haskell.org, включен в неявный импорт в каждом файле Haskell, где находится функция flip. С правой стороны вы можете щелкнуть "источник" и увидеть исходный код для перевода.
flip :: (a -> b -> c) -> b -> a -> c
flip f x y = f y x
Предложение where допускает локальные определения x=10
или y="bla"
. Вы также можете определять функции локально с тем же синтаксисом, что и для верхнего уровня. add x y = x + y
В приведенной ниже эквивалентной формулировке я делаю замену g = f y x
flip :: (a -> b -> c) -> b -> a -> c
flip f x y = g
where
g = f y x
В настоящий момент g не принимает никаких параметров. Но что, если бы мы определили g как g a b = f b a
ну, тогда мы бы имели:
flip :: (a -> b -> c) -> b -> a -> c
flip f x y = g x y
where
g a b = f b a
Нет, мы можем сделать небольшое алгебраическое аннулирование (если вы думаете об этом как алгебра из математического класса, вы будете достаточно безопасны). Сосредоточение на:
flip f x y = g x y
Отмените y с каждой стороны для:
flip f x = g x
Теперь отмените x:
flip f = g
и теперь вернем его в полном выражении:
flip :: (a -> b -> c) -> b -> a -> c
flip f = g
where
g a b = f b a
В качестве последнего косметического шага мы можем сделать замену a
на x
и b
на y
для восстановления функции до имен аргументов:
flip :: (a -> b -> c) -> b -> a -> c
flip f = g
where
g x y = f y x
Как вы можете видеть, это определение flip немного кругом, и то, что мы начинаем с прелюдии, прост и является определением, которое я предпочитаю. Надеюсь, что это поможет объяснить, как работает where
и как сделать небольшую алгебраическую манипуляцию кодом Haskell.
Ответ 2
flip'
не имеет доступа к x
и y
. Он получает аргумент f
и вычисляет выражение g
. Нет x
или y
в поле зрения.
Однако g
сама по себе является функцией, определяемой вспомогательным уравнением в предложении where
flip'
.
Вы можете читать g x y = f y x
точно так же, как если бы это было уравнение верхнего уровня, например flip'
. Итак, g
является функцией двух аргументов, x
и y
. Он g
имеет доступ к x
и y
, а не flip'
. Значения для этих аргументов не существуют до тех пор, пока не будет применено значение g
, и только после того, как flip'
вернет функцию g
(если когда-либо).
То, что особенно важно в g
, которое определено в where
-разделе flip'
, состоит в том, что оно может иметь доступ к аргументам flip'
, а именно, как g
можно определить в терминах f
.
Поэтому, когда вызывается flip'
, он получает функцию f
. Для каждого конкретного вызова flip'
он создает новую функцию g
. g
получит два аргумента x
и y
, когда он вызывается, но этого еще не произошло. flip'
затем просто возвращает g
в качестве результата.
Ответ 3
Найдите тип g
.
Мы знаем тип флип: (a -> b -> c) -> (b -> a -> c)
Поэтому мы можем вывести тип f
: (a -> b -> c)
Мы имеем это определение для g
g x y = f y x
Из правой части получаем, что y :: a
и x :: b
.
Следовательно, g :: b -> a -> c
Обратите внимание, что определение может быть переписано без предложения where.
flip' f = g where g x y = f y x
-> flip' f a b = g a b where g a b = f b a
-> flip' f a b = f b a
Ответ 4
Проще говоря, вы также можете определить функции в блоке where. Таким образом, переменные x
и y
являются только формальными параметрами g
и поэтому вы можете получить к нему доступ в g x y = f y x
: g x y
определяет формальные параметры x
и y
и f y x
это определение того, что делает g
. Наконец, это определение возвращается из flip f = g
.