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