Да, есть разница, потому что the ->
type constructor is right-associative. Другими словами,
a -> b -> f a -> f b
эквивалентно
a -> (b -> (f a -> f b))
Этот тип подписи обозначает функцию, которая принимает параметр типа a
и возвращает функцию, которая сама принимает параметр типа b
и возвращает функция, которая сама принимает параметр типа f a
и возвращает значение типа f b
.
С другой стороны,
(a -> b) -> f a -> f b
обозначает функцию, которая принимает параметр типа a -> b
(т.е. функция, которая принимает параметр типа a
и возвращает значение типа b
) и возвращает функцию, который сам принимает параметр типа f a
и возвращает значение типа f b
.
Вот надуманный пример, который иллюстрирует разницу между подписями на два типа:
f :: (Int -> Bool) -> [Int] -> [Bool]
f = map
g :: Int -> Bool -> [Int] -> [Bool]
g n b = map (\n' -> (n' == n) == b)
λ> let ns = [42, 13, 42, 17]
λ> f (== 42) ns
[True,False,True,False]
λ> g 42 True ns
[True,False,True,False]
λ> g 42 False ns
[False,True,False,True]
Как вопрос в тексте и вопрос в заголовке, связанных? Скобки в сигнатурах типа * не * обозначают специальную семантику, они для приоритета, как и везде в Haskell, поэтому два фрагмента * не * эквивалентны. –
@ JörgWMittag: Я согласен, что два вопроса не являются * эквивалентными * - и на самом деле имеют разные ответы, но я удивлен, что вы находите их * несвязанными *. Они оба касаются значения круглых скобок в сигнатурах типов; ответ «да» на вопрос в названии, вероятно, повлечет за собой «да» ответ на вопрос в тексте; и хороший ответ на любой вопрос, вероятно, косвенно (или даже явно) отвечает на другой вопрос. – ruakh
Скобки в титрах обозначают приоритет, как в терминах. Приоритет - это чисто синтаксическое свойство *, оно не имеет смыслового значения.Таким образом, круглые скобки в типах подписей не являются ни специальными, ни семантическими, а * that * - это то, почему два фрагмента не эквивалентны, так же как 'a + b * c' и' (a + b) * c' не эквивалентны, также потому, что синтаксического приоритета, а не из-за семантики. –