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?
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
).