Why is Equatable not defined for optional arrays

Can someone give me a good reason for why this doesn't work:

let a: [Int]? = [1]
let b: [Int]? = nil
a == b

This would be my proposed (if inelegant) solution. But it's trivial, so I feel like I'm missing a good reason why this isn't implemented.

func ==<T: Equatable>(lhs: [T]?, rhs: [T]?) -> Bool {

    if let lhs = lhs, let rhs = rhs {
        return lhs == rhs
    }
    else if let _ = lhs {
        return false
    }
    else if let _ = rhs {
        return false
    }

    return true
}

Update: Conditional conformance has been implemented in Swift 4.1. Arrays and optionals of Equatable elements are themselves Equatable now, and your code

let a: [Int]? = [1]
let b: [Int]? = nil
a == b

compiles and works as expected in Xcode 9.3. The workarounds are not needed anymore.


(Old answer:) Optionals can be compared only if the underlying wrapped type is equatable:

public func ==<T : Equatable>(lhs: T?, rhs: T?) -> Bool

Now Arrays can be compared if the element type is equatable:

/// Returns true if these arrays contain the same elements.
public func ==<Element : Equatable>(lhs: [Element], rhs: [Element]) -> Bool

but even for equatable types T, Array<T> does not conform to the Equatable protocol.

At present, this is not possible in Swift, see for example Why can't I make Array conform to Equatable? for a discussion in the Apple developer forum. This change with the implementation of SE-0143 Conditional conformances in Swift 4.

Your implementation looks correct, here is a possible different one using switch/case with pattern matching:

func ==<T: Equatable>(lhs: [T]?, rhs: [T]?) -> Bool {

    switch (lhs, rhs) {
    case let (l?, r?) : // shortcut for (.Some(l), .Some(r))
        return l == r
    case (.None, .None):
        return true
    default:
        return false
    }
}