0

Based on this article by John Sundell I have following struct:

protocol Identifiable {
    associatedtype RawIdentifier: Codable, Hashable = String

    var id: Identifier<Self> { get }
}

struct Identifier<Value: Identifiable>: Hashable {
    let rawValue: Value.RawIdentifier

    init(stringLiteral value: Value.RawIdentifier) {
        rawValue = value
    }
}

extension Identifier: ExpressibleByIntegerLiteral
          where Value.RawIdentifier == Int {
    typealias IntegerLiteralType = Int

    init(integerLiteral value: IntegerLiteralType) {
        rawValue = value
    }
}

It can be either String or Int. To be able to print it simply(without need to use .rawValue), I've added following extensions:

extension Identifier: CustomStringConvertible where Value.RawIdentifier == String {
    var description: String {
        return rawValue
    }
}

extension Identifier where Value.RawIdentifier == Int {
    var description: String {
        return "\(rawValue)"
    }
}

The problem is, it works only for extension which conforms to CustomStringConvertible, and the other one is ignored. And I can't add the conformance to the other extension as they would overlap.

print(Identifier<A>(stringLiteral: "string")) // prints "string"
print(Identifier<B>(integerLiteral: 5)) // prints "Identifier<B>(rawValue: 5)"
Adam Bardon
  • 3,829
  • 7
  • 38
  • 73

1 Answers1

1

You could use a single CustomStringConvertible extension instead of the two you have at the moment, regardless of type:

extension Identifier: CustomStringConvertible {
    var description: String {
        "\(rawValue)"
    }
}

For me this correctly prints "string" then "5" as per your last code example.

This coincidentally is what Sundell does in his open source Identity implementation of Identifiable/Identifier – https://github.com/JohnSundell/Identity/blob/master/Sources/Identity/Identity.swift#L72-L78

Point-Free's 'Tagged' implementation is also worth a look for reference: https://github.com/pointfreeco/swift-tagged/blob/master/Sources/Tagged/Tagged.swift

Seb Jachec
  • 3,003
  • 2
  • 30
  • 56