Stream: beginners

Topic: Formatter inconsistently drops parens in the type definition


view this post on Zulip Kiryl Dziamura (Jan 25 2024 at 18:47):

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

view this post on Zulip Brian Teague (Jan 25 2024 at 19:20):

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

view this post on Zulip Kiryl Dziamura (Jan 25 2024 at 19:25):

The parser sees it differently (as I described, it assumes ((a, b) -> c) -> d). So it's a bug for the parser then

view this post on Zulip Brian Teague (Jan 25 2024 at 19:32):

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

view this post on Zulip Brian Teague (Jan 25 2024 at 19:34):

Those extra parenthesis should not be dropped.

view this post on Zulip Brendan Hansknecht (Jan 25 2024 at 19:35):

Your original type is correct. So formatter bug. It needs to put parens around closure type definitions if they aren't top level.

view this post on Zulip Brendan Hansknecht (Jan 25 2024 at 19:36):

I guess this was missed ambiguity that got added when we added the tuple syntax

view this post on Zulip Brian Teague (Jan 26 2024 at 01:00):

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

view this post on Zulip Folkert de Vries (Jan 26 2024 at 22:39):

the actual bug would be in the parser, right?

view this post on Zulip Brendan Hansknecht (Jan 26 2024 at 23:06):

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