Можно ли использовать унарную функцию вместо бинарной в `flip`? - PullRequest
10 голосов
/ 11 ноября 2009

Тип функции Prelude flip:

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

Т.е., требуется одна двоичная функция и два аргумента.

Тип функции Prelude id:

id :: a -> a

Но тип flip id:

flip id :: a -> (a -> b) -> b

Как можно применить flip к id, когда id является унарной функцией и flip требует двоичной функции для первого аргумента?

кстати. flip id похоже на \ x f -> f x

Ответы [ 2 ]

15 голосов
/ 11 ноября 2009

Haskell заставляет id соответствовать типу первого аргумента для flip путем установки a = b -> c. Итак:

flip :: ( a       -> b -> c) -> b ->  a       -> c
flip :: ((b -> c) -> b -> c) -> b -> (b -> c) -> c
flip id ::                      b -> (b -> c) -> c

где id относится к типу

id :: (b -> c) ->  b -> c

, что эквивалентно

id :: (b -> c) -> (b -> c)

т.е. специализация id, которая применяется только к унарным функциям.

Редактировать: я думаю, что я мог бы перефразировать мою первую строку как:
Haskell выводит , что id соответствует типу первого аргумента для flip , если a = b -> c.
На случай, если это станет понятнее.

4 голосов
/ 11 ноября 2009

Нефрубыр объясняет это очень хорошо.
Еще один способ (надеюсь) сделать это немного более интуитивным - подумать об операторе приложения функции ($).

($) является специализированной формой id:

($) :: (a -> b) -> (a -> b)
($) = id

Я видел определение (#) = flip ($), такое, что вы можете написать аргумент до того, как функция будет применена к: obj # show.

Очевидно, что ($) - это просто специализированная форма id, вы также можете написать: (#) = flip id

...