Hi everyone from a long time lurker, first time poster.
I've been tinkering with Roc for a while now (exercises on exercism.org, Advent of Code etc.) and I've come across an annoying inconsistency in the way Set equality is handled. Everything is fine until you enclose the Set in a tag or record at which point the insertion order suddenly matters and previously equal Sets no longer compare as equal.
This snippet from a repl session shows the issue:
» s1 = [1,2,3,4] |> Set.from_list
@Set (...) : Set (Num *)
» s2 = [4,3,2,1] |> Set.from_list
@Set (...) : Set (Num *)
» s1 == s2
Bool.true : Bool
» Ok(s1) == Ok(s2)
Bool.false : Bool
» s3 = [1,2,3,4] |> Set.from_list
@Set (...) : Set (Num *)
» Ok(s1) == Ok(s2)
Bool.false : Bool
» Ok(s1) == Ok(s3)
Bool.true : Bool
»
The same behaviour occurs for records.
Is this a bug or is this the intended behaviour?
Hi @Simon Redding,
I think this is a bug, @Brendan Hansknecht may be most familiar with the implementation of this.
Yeah, this is a known bug with how the equality ability is derived
Some reason the ability derivation is completely structural for anything nested
Would this be fixed with static dispatch?
The only userland solution I know of is to make the wrapping tag an opaque type and write the implementation of eq
Anton said:
Would this be fixed with static dispatch?
I would hope so. At a minimum, the system is a full rewrite that will need to deal with this problem itself.
Thanks guys.
This is mainly impacting unit tests for me so unpacking the tags/records isn't the end of the world.
I see that there's already an issue in GitHub for this: Order matters when sets comparing sets/dicts nested in other types (tags, records, etc) · Issue #7111 · roc-lang/roc
Last updated: Jul 06 2025 at 12:14 UTC