Search code examples
functional-programmingsml

SML: Rigorous Way To Parenthesize Function Type


I'm having a bit of difficulty figuring out how to parenthesize a function (when it's legal to add parentheses around certain parts to make the meaning clearer).

For instance, foldl is defined as having type:

foldl : ('a * 'b -> 'b) -> b -> 'a list -> 'b

Now, if I look at foldl's definition, I see:

fun foldl g z [] = z
    | foldl g z (x::L) = foldl g (g(x,z)) L;

Based on this, I usually just mentally map g to ('a * 'b -> 'b), z to be of type 'b, and pattern-matching takes care of the list of type 'a list. Finally, the return type is 'b.

However, I thought -> right associates, so wouldn't it be most natural to start by saying "OK, add parentheses like so:

foldl : ('a * 'b -> 'b) -> 'b -> ('a list -> 'b)

What's wrong with this line of thought / what am I misunderstanding about how to add parentheses?


Solution

  • There's nothing wrong with it, it's just redundant.

    ('a * 'b -> 'b) -> 'b -> ('a list -> 'b), ('a * 'b -> 'b) -> ('b -> ('a list -> 'b)) and ('a * 'b -> 'b) -> 'b -> 'a list -> 'b are all equivalent because -> is right associative. So we usually write the version with the least parentheses (just like one usually writes 3 - 2 - 1 rather than the equivalent (3 - 2) - 1).