Take the type signature of fmap
(the Functor
method) as an example:
(a -> b) -> f a -> f b
How is that different from the following type signature?
a -> b -> f a -> f b
Is there even a difference between those two type signatures?
Haskell uses parentheses only in the way they are used in high school mathematics: for grouping sub-expressions so that you get a different call structure. For example, in maths 1 + 2 * 3 would call * on 2 and 3, and call + on 1 and the result of the * call.
From HaskellWiki. A type signature is a line like. inc :: Num a => a -> a. that tells, what is the type of a variable. In the example inc is the variable, Num a => is the context and a -> a is its type, namely a function type with the kind * -> * .
Yes, there is a difference, because the ->
type constructor is right-associative. In other words,
a -> b -> f a -> f b
is equivalent to
a -> (b -> (f a -> f b))
This type signature denotes a function that takes a parameter of type a
and returns a function, which itself takes a parameter of type b
and returns a function, which itself takes a parameter of type f a
and returns a value of type f b
.
On the other hand,
(a -> b) -> f a -> f b
denotes a function that takes a parameter of type a -> b
(i.e. a function that takes a parameter of type a
and returns a value of type b
) and returns a function, which itself takes a parameter of type f a
and returns a value of type f b
.
Here is a contrived example that illustrates the difference between the two type signatures:
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]
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With