Another example of questionable behaviour in my opinion.
Here is a piece of code i had:
parse_template_recursive : List U8, List (Spec _) -> Result (List (Spec _)) [InvalidTemplate([MissingClosingBracket])]
parse_template_recursive = |template_codes, acc|
when split_first_segment(template_codes) is
Err(ListWasEmpty) -> Ok(acc)
Err(MissingClosingBracket) -> MissingClosingBracket |> InvalidTemplate |> Err
Ok({before : ['{', .. ,'}'], others}) -> crash("Not implemented yet")
Ok({before, others}) -> crash("Not implemented yet")
split_first_segment
may currently return only 2 types of errors: ListWasEmpty
and MissingClosingBracket
, but in the feature may be extended with other errors. Should the pattern matcher be smart enough to understand this:
parse_template_recursive : List U8, List (Spec _) -> Result (List (Spec _)) [InvalidTemplate([MissingClosingBracket])]
parse_template_recursive = |template_codes, acc|
when split_first_segment(template_codes) is
Err(ListWasEmpty) -> Ok(acc)
Err(reason) -> reason |> InvalidTemplate |> Err
Ok({before : ['{', .. ,'}'], others}) -> crash("Not implemented yet")
Ok({before, others}) -> crash("Not implemented yet")
Because currently even if I do handle a case when ListWasEmpty
has being thrown I still get an error:
TYPE MISMATCH
Something is off with the body of the
`parse_template_recursive` definition:
120│ parse_template_recursive : List U8, List (Spec _) -> Result (List (Spec _)) [InvalidTemplate([MissingClosingBracket])]
121│ parse_template_recursive = |template_codes, acc|
122│> when split_first_segment(template_codes) is
123│> Err(ListWasEmpty) -> Ok(acc)
124│> Err(reason) -> reason |> InvalidTemplate |> Err
125│> Ok({before : ['{', .. ,'}'], others}) -> crash("Not implemented yet")
126│> Ok({before, others}) -> crash("Not implemented yet")
This `when` expression produces:
[
Err [InvalidTemplate [
ListWasEmpty,
MissingClosingBracket,
]],
Ok (List (Match.Spec c)),
]
But the type annotation on
`parse_template_recursive` says it should be:
Result (List (Match.Spec c)) [InvalidTemplate [MissingClosingBracket]]
Should the pattern matcher be smart enough to understand this
Yes, it should be but it is quite limited at the moment. I'll make an issue.
No this should not work
As much as it feels it should
Roc has no gradual typing
The type of reason
is [ListWasEmpty, MissingClosingBracket]
Think of it like this. If you had an enum Color: [Red, Green, Blue]
. Even if the function is guaranteed to return Blue
, the type is still Color
. The same thing is happening here
I know this has been discussed in the past, but I don't think there are any current plans to add gradual typing for tag unions.
No this should not work
Yeah, I was doubting as well when I wrote up the issue. I'll close it.
Got it, thanks.
Last updated: Jul 06 2025 at 12:14 UTC