2014-12-24 4 views
3

Brent Йорги отличного UPenn Haskell course представляет:Типов функций Связанных с аргументами

fmap2 :: Functor f => (a -> b -> c) -> (f a -> f b -> f c) 
fmap2 h fa fb = undefined 

Типы h, fa и fb ломаются до:

h :: a -> b -> c 
fa :: f a 
fb :: f b 

Это мне не ясно, почему h относится к целая функция (a -> b -> c).

Почему нет h обратитесь к a и fa обратитесь к (b -> c)?

Составляются ли скобки в (a -> b -> c)?

EDIT

Рассмотрим leftaroundabout «s comment:

Для тех, кто просто читает это, не зная конкретного курса говорится: fmap2 не может быть определена с этой подписью.

Это на самом деле должно быть liftA2 :: Applicative a => (a->b->c) -> (f a->f b->f c)

+3

Для тех, кто просто читает это, не зная конкретного курса, на который ссылается: 'fmap2' не может быть определен с этой подписью. На самом деле это должно быть 'liftA2 :: Применительно a => (a-> b-> c) -> (f a-> f b-> f c)'. – leftaroundabout

ответ

12

Да, скобки делают разницу в точности, как вы говорите. Поскольку (->) является right-associative, но не mathematically associative, выражение в скобках в левой части функции стрелка не может быть разделена так, как вы предполагаете:

(a -> b) -> (f a -> f b) /= a -> b -> f a -> f b 

Оператор -> в связи с этим так же, как оператор возведения в степень , ^, что notationally правоассоциативный но not mathematically associative:

(2^2)^(2^2) /= 2^2^2^2 
4  ^4  /= 2^(2^(2^2)) 
256    /= 2^(2^4) 
256    /= 2^16 
256    /= 65536 

(аналогия с экспоненциацией не мое изобретение, типы функций являются «экспоненциальными типами» в том же смысле, что (a, b) является «тип продукта» и Either a b - «тип суммы». Но учтите, что a -> b аналогичен b^a, а не a^b. See this blog post for an example-heavy explanation; также this answer gives a mathematical overview of type algebra.)

Очевидная странность с fmap2, что тип выглядит он принимает один параметра, но определение выглядит она занимает три. Сравним эту версию, которая мне по крайней мере больше похож на тип подписи:

fmap2 :: Functor f => (a -> b -> c) -> (f a -> f b -> f c) 
fmap2 h = \fa fb -> undefined 

Теперь у нас есть хороший «один-аргумент» вещь, fmap2 h = ..., с «двумя аргументами» лямбда справа. Фокус в том, что в Haskell эти два выражения эквивалентны [*]: Haskell Report говорит, что форма «функции» с параметрами на LHS «семантически эквивалентна» простой привязке шаблона лямбда.

Вы также можете переписать тип устранить скобки на правой стороны стрелки, опять же из--> является правоассоциативным:

(a -> b -> c) -> (f a -> f b -> f c) 
== (a -> b -> c) -> f a -> f b -> f c 

так же, как

(2^2^2)^(2^2^2) 
== (2^2^2)^2^2^2 

[* ]: Они семантически эквивалентны, но при компиляции с GHC характеристики могут и иногда различаться. Оптимизатор GHC обрабатывает f x = ... и f = \x -> ... по-разному.

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