If I have a function, that returns a tag like [A,B,C]
, and I want to compare it with a tag like this [A, B]
, is that possible?
For example:
func : {} -> [A, B, C]
func = \_ -> C
otherFunc : [A, B] -> Bool
otherFunc = \ab ->
func {} == ab
If I run this, I get an error like
This ab value is a:
[…]
But == needs its 2nd argument to be:
[C, …]
Ah. I found a solution. I can use [A, B]_
instead of [A, B]
.
otherFunc : [A, B]_ -> Bool
otherFunc = \ab ->
func {} == ab
But is this really necessary? If the argument to otherFunc
should only be A
or B
, then the _
seems wrong. Would it be possible to compare any tags and just return Bool.false
, if they do not intersect?
My understanding is that equality checks via ==
are derived for specific types, and return true for things that are "structurally" the same
So as much as the code makes the types [A, B]
and [A, B, C]
look the same because two of the variants have the same name, the overall types are actually different
The _
is actually just a type hole, not a generic parameter, so it'll resolve to a specific type here, meaning that [A, B]_
is resolving to [A, B]
only, and not [A, B, C]
as well.
For us to implement equality checks between different types is a bit of a rabbit hole... Do we only allow it for tag unions where one is a subset of the other? What if each union has variants missing from the other?
So for now, we'd probably expect you to do one of two things:
Write a match expression:
when (ab, abc) is
(A, A) -> Bool.true
(B, B) -> Bool.true
_ -> Bool.false
Or keep the [A, B]
variant in a parent to make the [A, B]
type equal:
MyType : [AB [A, B], C]
when myType is
AB myAb -> myAb == ab
C -> Bool.false
It's both not so nice. I think I will stay with [A, B]_ for the moment, even when it's not correct
So for now, we'd probably expect you to do one of two things:
This is a contrived example, so it is hard to say for sure, but I think the recommendation today would be to not try and compare two different types. Instead architect the code differently.
This is kinda like trying to compare two different c++ enums that happen to have some tags with the same names.
When I think about it, I get it. If I had this types: [A, B, C]
and [B, C]
. In memory, the B
from the first type is represented as 1
and the one from the second tag as 0
. If you write B == B
it would look like 1 == 0
in memory. If roc should be able to compare them, roc would need to convert the types.
I get, that this is something, that should be avoided. But when I just look at the roc code, it is strange at first, that B == B
is a type error.
Yeah, totally agree with that being strange. The issue with not namespacing or qualifying our tags in some way
Cause it really should be: Union1::B == Union2::B
Brendan Hansknecht said:
Yeah, totally agree with that being strange. The issue with not namespacing or qualifying our tags in some way
A cost that is totally worth opting into, but is definitely a cost
Last updated: Jul 06 2025 at 12:14 UTC