Search code examples
haskelltypesparentheses

What is the meaning of parentheses in Haskell type signatures?


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?


Solution

  • 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]