Conforming Tuples to Protocols
Tuples in Swift are a great way to quickly combine two or more pieces of data. For example, when working on an SVG parsing library, we had two doubles that we wanted to combine. In some cases it's very helpful to create a nominal type, such as a Point
:
struct Point {
var x: Double
var y: Double
}
In other cases, we can't always come up with a good name. Perhaps we're working on something more abstract, or the two values could be interpreted in different ways: in one case they might be points, in another they're interpreted as sizes. Instead of a nominal type, we'd use a structural type such as a tuple:
struct MyModel {
var pairs: [(Double, Double)]
}
The major disadvantage of using a tuple to model data — as we do above with (Double, Double)
— is that a tuple can't conform to a protocol. This means we can't just add Equatable
, Hashable
, or Codable
conformance using the implementation we'd otherwise get for free. If we had written our pairs
property as [Point]
instead, this would be much easier.
However, all is not lost. We can write a type Pair<A, B>
that works in the same way as a tuple, but also adds conditional conformance. Here's one possible implementation:
struct Pair<A, B> {
var one: A
var two: B
init(_ one: A, _ two: B) {
self.one = one
self.two = two
}
}
Now we can conditionally conform Pair
to all kinds of protocols:
extension Pair: Encodable where A: Encodable, B: Encodable { }
extension Pair: Decodable where A: Decodable, B: Decodable { }
extension Pair: Equatable where A: Equatable, B: Equatable { }
extension Pair: Hashable where A: Hashable, B: Hashable { }
We can even conform Pair
to SwiftUI's VectorArithmetic
protocol, so that it can be used with animatableData
.
Of course, a Pair
doesn't have all the same syntactic sugar as a tuple, but it can be a quick alternative in case we want a structural type that can conform to Codable
(or any other protocol):
struct MyModel {
var pairs: [Pair<Double, Double>]
}
Until Swift adds conditional conformance to tuples, this is a workaround that has served us well in a few projects.
Many of our projects feature in Swift Talk, our weekly pair programming video series. The most recent collection explores SwiftUI, as we build a client app for our Swift Talk backend.
To learn with us, subscribe here.