Order matters when sets comparing sets/dicts nested in other types (tags, records, etc)
All of these expects should pass, but the last one fails:
# Passes
expect Set.fromList [1, 2] == Set.fromList [1, 2]
# Passes
expect Set.fromList [1, 2] == Set.fromList [2, 1]
# Passes
expect Ok (Set.fromList [1, 2]) == Ok (Set.fromList [1, 2])
# Fails
expect Ok (Set.fromList [1, 2]) == Ok (Set.fromList [2, 1])
Context from Brendan:
Wild guess. We aren't correctly resolving abilities and using the opaque set equality operator when it is wrapped in a tag. Instead, it is doing a raw comparison of the internal impl as if the opaque type wasn't there.
This issue also affects records. I've opened a separate issue #7144, but feel free to close it if you think it's the same underlying cause.
As @bhansconnect suggested, I can confirm that isEq does not seem to be called. Here's a little module defining a CustomSet opaque type:
# CustomSet.roc
module [create, isEq]
CustomSet := { items : List U64 } implements [Eq]
create : List U64 -> CustomSet
create = \items ->
@CustomSet { items }
isEq : CustomSet, CustomSet -> Bool
isEq = \@CustomSet { items: items1 }, @CustomSet { items: items2 } ->
List.sortAsc items1 == List.sortAsc items2
And here's a program that creates two CustomSet values and compares them with == and isEq: the results differ.
# test-custom-set.roc
app [main] {
pf: platform "https://github.com/roc-lang/basic-cli/releases/download/0.15.0/SlwdbJ-3GR7uBWQo6zlmYWNYOxnvo8r6YABXD-45UOw.tar.br",
}
import pf.Stdout
import CustomSet
main =
set1 = CustomSet.create [1, 2, 3]
set2 = CustomSet.create [3, 2, 1]
result1 = set1 == set2
result2 = set1 |> CustomSet.isEq set2
Stdout.line! (result1 |> Inspect.toStr)
Stdout.line! (result2 |> Inspect.toStr)
The output is:
Bool.false
Bool.true