Search code examples
swiftsequenceequatable

How can I get Sequence to implement Equatable?


I have the following best attempt:

extension Equatable where Self: Sequence, Self.Element: Equatable {
    public static func == (lhs: Self, rhs: Self) -> Bool {
        return lhs.elementsEqual(rhs)
    }
}

But it doesn't seem to work. Furthermore, it requires both sequences to have the same exact type, whereas I only want to constraint that their Element types be the same. Is there any way to do this?


Solution

  • Protocols never conform to other protocols. Protocols can require other protocols (which we typically call "protocol inheritance"), but this does not make protocols conform to other protocols. Protocols don't even conform to themselves, let alone something else. Sequence.self cannot be passed to things that require a Sequence.Type.

    In any case, Equatable requires that the things being compared be of the same type. Other meanings of "equal" are not Equatable.

    If you want to build methods on top of "these two sequences have the equal elements," that's fine. That's what elementsEqual does for you already. But that doesn't make them Equatable.

    What algorithm are you trying to build that would use this and that elementEqual doesn't already handle?

    It's possible what you're looking for is just some syntactic sugar to make it look like ==. That's no problem at all. You can build any operator you want to implement elementsEqual.

    infix operator ~=
    
    func ~= <S1, S2>(lhs: S1, rhs: S2) -> Bool
        where S1: Sequence, S2:Sequence,
        S1.Element: Equatable, S1.Element == S2.Element
    {
        return lhs.elementsEqual(rhs)
    }
    

    I usually recommend against custom operators, but if you are doing a lot of this kind of work, an explicit "these sequences have equal values in the same order" operator may be very useful. You just wouldn't want to use ==, because that already means something that this doesn't mean. For example, two Sets may be ==, but not ~=, so you need to choose the tool you mean.