Formatter transforms this type
x : (a, (b -> c)) -> d
to
x : (a, b -> c) -> d
Originally, (a, (b -> c))
is a tuple with two items a
and b -> c
But after formatting it becomes (a, b -> c)
which is a function with two arguments
Created an issue
https://github.com/roc-lang/roc/issues/6426
The above example is still only one argument as a tuple.
x : (a, b->c) is equivalent to x: (a, (b->c)) which is why the parenthesis were dropped.
x has one argument, tuple, with values a and function b->c
Two separate arguments would look like this.
x: a, (b->c) -> d
The parser sees it differently (as I described, it assumes ((a, b) -> c) -> d
). So it's a bug for the parser then
You're right. This grammar is ambiguous.
(a, b-> c) -> d
Is it a tuple with type a
and type function b -> c
, or is it a function with two args a, b -> c
Those extra parenthesis should not be dropped.
Your original type is correct. So formatter bug. It needs to put parens around closure type definitions if they aren't top level.
I guess this was missed ambiguity that got added when we added the tuple syntax
Just to document an additional edge cases:
x: (a, (b, c -> d)) -> e
x: (a, b, (c->d)) -> e
x: a, (b, c -> d) -> e
x: a, b, (c -> d) -> e
the actual bug would be in the parser, right?
It is the formatter failing.
Slightly simpler example:
Original: x: (A, (B -> C))
Formatted x : (A, B -> C)
It correctly parses the first expession as a tuple that contains a value A
and a function B -> C
.
When formatting and printing that back out, it needs to put the function B -> C
into parens otherwise, it will be invalid.
parsed expression
Formatting failed and gave us (A, B -> C)
, that said, it does parse the wrong expression correctly.
(A, B -> C)
is a function A
and B
to C
.
formatted then reparsed expression
Last updated: Jul 06 2025 at 12:14 UTC