# [Haskell-beginners] types, parentheses, application, composition

Sun Nov 25 14:43:47 CET 2012

```On Sonntag, 25. November 2012, 02:27:31, Christopher Howard wrote:
> Could someone explain more precisely to me what is the significance of
> parentheses in the type of an expression? Are they just some kind of
> syntactic sugar, that simplifies into a type without them, or are they
> more like parentheses in algebra, or...?

More like parentheses in algebra, they serve to group together parts of a
(type) expression that would be grouped differently by the precedence and/or
associativity of operators, e.g. in

foo :: (Int -> a) -> a
foo f = f 42

The function arrow associates to the right, so without them, the signature
would become  Int -> (a -> a) which is an entirely different type.

Or

bar :: Either a (b -> a) -> b -> a

where it's precedence. Prefix type application binds strongest (like function
application at the value level), so we can't omit the parentheses, otherwise
we'd get

(Either a b) -> a -> b -> a

>
> In particular, I'm having difficulty understanding the results of
> composition or application that involves parentheses... I think I've got
> it figured out and then I find another strange expression that doesn't
> have the type I expect. Here is an example using the (self-made)
> function "sqr":
>
> code:
> --------
>
> > :t sqr
>
> sqr :: Double -> Double
>
> > :t (.)
>
> (.) :: (b -> c) -> (a -> b) -> a -> c

Let's be more verbose and call it

(.) :: (intermediate -> final) -> (original -> intermediate)
-> original -> final

>
> > :t (. sqr)

The section (. sqr) is equivalent to \f -> f . sqr, so sqr is the second
argument of (.) and we must unify its type with the type of the second
argument of (.), which is (original -> intermediate).

So original = Double, intermediate = Double, and here (.) is used at the more
restricted type

(.) :: (Double -> final) -> (Double -> Double) -> Double -> final

the second argument is supplied, hence its type is removed, leaving

(. sqr) :: (Double -> final) -> Double -> final

>
> (. sqr) :: (Double -> c) -> Double -> c

Yup, modulo renaming, we have exactly that.

>
> > :t ((. sqr) .)

Now, (. sqr) is used as the first argument of (.). So we must unify its type
with (intermediate -> final), the type of (.)'s first argument.

Now, the function arrow is right-associative, so we can also write

(. sqr) :: (Double -> c) -> (Double -> c)

and that makes it clear that

intermediate = (Double -> c)
final = (Double -> c)

So the outer (.) is used at type

(.) :: ((Double -> c) -> (Double -> c)) -> (original -> (Double -> c)) ->
original -> (Double -> c)

The first argument is supplied, so

((. sqr) .) :: (original -> (Double -> c)) -> original -> (Double -> c)

>
> ((. sqr) .) :: (a -> Double -> c) -> a -> Double -> c

Yup, modulo renaming and parentheses that can be omitted because -> is right-
associative, that is exactly the same.

It's just easier to see what corresponds to what with the parentheses.

> --------
>
> Everything makes sense up until the last expression, "((. sqr) .)".
> Where did the "(a -> Double -> c)" come from? What's going on here?

The pretty-printer of type signatures in ghci omits unnecessary parentheses.
Read it (a -> (Double -> c)).

While for small types like here, unnecessary parentheses can increase the