Что означает скобки в сигнатурах типа Haskell?

возьмите подпись типа fmap (the Functor способ) в качестве примера:

(a -> b) -> f a -> f b

чем это отличается от подписи следующего типа?

a -> b -> f a -> f b

есть ли разница между этими двумя сигнатурами типов?

3 ответов


Да, есть разница, потому что на -> конструктор типа право-ассоциативной. Другими словами,

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]

да

(a -> b) -> ...

означает " заданная функция, которая принимает a в b ...". А этот

a -> b -> ...

означает " учитывая некоторые a и некоторые b..."


Да (a -> b) означает один аргумент, который является функцией с подписью a -> b, тогда как a -> b -> ... значит два аргумента.