How can we compare parameterized types ignoring parameter types?

How can we compare parameterized types ignoring parameter types?


fn main() raises:
    a = Kinded[Kind.Good](42)
    b = Kinded[Kind.Bad](42)
    print(a == b)
    

@fieldwise_init
struct Kind(Copyable):
    var v: Int

    alias Good = Kind(0)
    alias Bad = Kind(1)


@fieldwise_init
struct Kinded[k: Kind](Copyable & EqualityComparable):
    var _value: Int

    fn __eq__(self: Kinded[Kind.Good], other: Kinded[Kind.Bad]) -> Bool:
        return self._value == other._value

    fn __ne__(self: Kinded[Kind.Good], other: Kinded[Kind.Bad]) -> Bool:
        return not (self == other)    

The above does not work. Can we make them work? Is there a generic way too?

It’s unfortunate that we can’t have a Eq conforming heterogeneous equity without generic traits or something equivalent.

That said, workarounds may exist for your particular use case. Could you elaborate on what you mean by “make them work”?

Hi @ratulb !

Currently your specific implementation unfortunately won’t work due to how the EqualityComparable trait is defined

trait EqualityComparable:
    fn __eq__(self, other: Self) -> Bool:

The trait requires self and other to both be of the same type and cannot have their parameter value k set specifically. Making EqualityComparable work for this would require some combination of: generic traits, a rework to the trait itself, relaxing the trait requirements, and may also require some support for conditional conformance (which the languages doesn’t have yet).

All that being said, for you example if you simply remove EqualityComparable

struct Kinded[k: Kind](Copyable):

You can still define the __eq__ and __ne__ as you have them laid out. This will allow you to use the == and != operators for your type - you just won’t be able to pass it to any functions that require EqualityComparable

@fieldwise_init
struct Kind(Copyable):
    var v: Int

    alias Good = Kind(0)
    alias Bad = Kind(1)


@fieldwise_init
struct Kinded[k: Kind](Copyable, Movable):
    var _value: Int

    fn __eq__(self: Kinded[Kind.Good], other: Kinded[Kind.Bad]) -> Bool:
        return self._value == other._value

    fn __ne__(self: Kinded[Kind.Good], other: Kinded[Kind.Bad]) -> Bool:
        return not (self == other)    

def main():
    var good = Kinded[Kind.Good](1)
    var bad = Kinded[Kind.Bad](2)
    assert_false(good == bad) 
    assert_true(good != bad)

Getting rid of `EqualityComparable` solves it. Thanks.

Got rid of `EqualityComparable` and it works. Thanks.

1 Like