2
votes

In Swift 2.1 (running XCode 7.2), I am trying to have a Protocol with associated type conform to Equatable.

// (#1)

/**
A Node in a graph
*/
public protocol GraphNode : Equatable {

    typealias Content : Equatable

    /**
     The content of the node.
     E.g. in a graph of strings, this is a string
     */
    var content: Content {get}

    /// The list of neighbours of this Node in the graph
    var children: [Self] {get}
}

As we could have non-homogeneous implementations of the protocol that define a different type for the associated type, I expect that I won't be able to define here (at the protocol level, not at the implementation level) an equality function:

// (#2)

/// Won't compile, as expected
public func ==(lhs: GraphNode, rhs: GraphNode) {
    return lhs.content == rhs.content
}

This is because I have no guarantee that lhs.Content is the same type as rhs.Content. However I was hoping I could specify it with some generic constraint, such as:

// (#3)

/// Won't compile, why?
public func ==<Node1 : GraphNode, Node2 : GraphNode where Node1.Content == Node2.Content>(lhs: Node1, rhs: Node2) 
{
    return lhs.content == rhs.content  // ERROR: Binary operator '==' cannot be applied to two 'Node1.Content' operands
}

In #3, we know that both lhs and rhs have the same type, and we know (from the specification of the associated type as Equatable) that Content is equatable. So why can't I compare them?

1

1 Answers

1
votes

Add -> Bool. Just a bad error message. Sometimes writing function declaration across multiple lines doesn't make it more readable.

public func ==<Node1 : GraphNode, Node2 : GraphNode where Node1.Content == Node2.Content>(lhs: Node1, rhs: Node2) -> Bool {

    return (lhs.content == rhs.content)

}