1
votes

I am working on building a flexible data structure in Swift called Node that, by itself, is not tied to any type of content. However, the Payload data within the Node is declared as the following generic Element struct that conforms to the Equatable protocol:

public struct Element<T>: Equatable {
  var data: T;
}

public func ==<T:Equatable>(lhs: Element<T>, rhs: Element<T>) -> Bool {
    return lhs.data == rhs.data;
}

The constraint is that the Element has to be tied to an equatable class type. The problem I'm having is with the Node containing this Element. The Node would be used in a Dictionary, Array, or any other container type. Here is what I have:

public class Node: Equatable {

    var payload: Element<AnyObject>

    init(_data: Element<AnyObject>) {
        self.payload = _data
    }

}

public func ==(lhs: Node, rhs: Node) -> Bool {
    return lhs.payload == rhs.payload;
}

Of course, I'm getting the error that AnyObject does not conform to Equatable. Is there any way to constrain the declaration of the payload to only Objects that are equatable? At this point, I don't know what kind of objects may be stored in the payload.

Also just realized I need to put a class check in the == function in Node to make sure the two Node payloads are compatible to be compared--don't need them to be.

Thoughts? Thank you!

1
Your second == implementation refers to lhs.data and rhs.data where lhs and rhs are Nodes. But your Node class has no data property, so I don't see what that's supposed to mean. Did you mean lhs.payload and rhs.payload?matt
Yes. I made some simplifications and forgot to change that. It should read lhs.payload and rhs.payloadAlex Ackerman

1 Answers

1
votes

In order to constrain payload to a type that is Equatable, you'll need Node to be a generic class so that it can pass along that constraint.

You can specify the constraint in your class declaration:

public class Node<T: Equatable>: Equatable {...}

And then when declaring your payload you can set its Element type to just T:

var payload: Element<T>

When testing the code, I had to also make the generic constraint, T, in Element conform to Equatable. Entire code for reference:

public struct Element<T: Equatable>: Equatable {
    var data: T
}

public func ==<T:Equatable>(lhs: Element<T>, rhs: Element<T>) -> Bool {
    return lhs.data == rhs.data
}

public class Node<T: Equatable>: Equatable {
    var payload: Element<T>
    init(_data: Element<T>) {
        self.payload = _data
    }
}

public func ==<T: Equatable>(lhs: Node<T>, rhs: Node<T>) -> Bool {
    return lhs.payload == rhs.payload
}

This will produce the following results:

Node(_data: Element(data: 1)) == Node(_data: Element(data: 1)) // true
Node(_data: Element(data: 1)) == Node(_data: Element(data: 2)) // false