Upgrade to Pro — share decks privately, control downloads, hide ads and more …

🏷 Tagged

to4iki
April 19, 2018

🏷 Tagged

potatotips #50
2018/04/19
https://potatotips.connpass.com/event/82476/

`Tagged`を使ったId型作成の話
https://github.com/pointfreeco/swift-tagged

to4iki

April 19, 2018
Tweet

More Decks by to4iki

Other Decks in Programming

Transcript

  1. !
    Tagged
    potatotips #50
    2018/04/19
    @to4iki
    1

    View full-size slide

  2. Me
    • Takezawa Toshiki
    • @to4iki
    • iOS Engineer
    • builderscon

    ! ☕ ♨
    2

    View full-size slide

  3. IdΛܕԽ͍ͨ͠
    (user.id ͱ subscription.idΛ۠ผ)
    3

    View full-size slide

  4. ex. 1
    struct User: Decodable {
    typealias Id = String
    let id: Id
    let subscriptionId: Subscription.Id
    }
    struct Subscription: Decodable {
    typealias Id = String
    let id: Id
    }
    4

    View full-size slide

  5. !
    not type-safety
    // typealias User.Id = String
    func fetchUser(with id: User.Id) -> User?
    fetchUser(with: user.id) // OK
    fetchUser(with: user.subscriptionId) // OK
    fetchUser(with: "123") // OK
    5

    View full-size slide

  6. !
    type-safety
    struct User: Decodable {
    struct Id: Decodable { let value: String }
    ...
    }
    func fetchUser(with id: User.Id) -> User?
    fetchUser(with: user.id) // OK
    fetchUser(with: user.subscriptionId) // Compile Error
    fetchUser(with: "123") // Compile Error
    6

    View full-size slide

  7. ex. 2
    { "id": "abc", "subscriptionId": "123" }
    // decode to `User`
    let decoder = JSONDecoder()
    let user = try! decoder.decode(User.self, from: Data(json.utf8))
    7

    View full-size slide

  8. !
    DecodingError.typeMismatch at User.Id
    Fatal error: 'try!' expression unexpectedly raised an error:
    Swift.DecodingError.typeMismatch(Swift.Dictionaryg, Any>, Swift.DecodingError.Context(codingPath:
    [CodingKeys(stringValue: "id", intValue: nil)],
    debugDescription: ...
    8

    View full-size slide

  9. !
    DecodableΛ໌ࣔతʹ࣮૷͢Δ
    struct User: Decodable {
    struct Id: Decodable {
    let value: String
    init(from decoder: Decoder) throws {
    let container = try decoder.singleValueContainer()
    self.value = try container.decode(String.self)
    }
    }
    ...
    }
    9

    View full-size slide

  10. ΋ͬͱεϚʔτʹղܾͰ͖ͳ͍͔ͳ
    10

    View full-size slide

  11. SE-0143: Conditional Conformance1
    /// Swift4
    /// Returns `true` if these arrays contain the same elements.
    public func ==(lhs: [Element], rhs: [Element]) -> Bool
    where Element : Equatable
    /// Swift4.1
    extension Array: Equatable where Element: Equatable {
    static func ==(lhs: Array, rhs: Array) -> Bool
    }
    [1,2,3] == [1,2,3] // ok
    1 https://github.com/apple/swift-evolution/blob/master/proposals/0143-conditional-conformances.md
    https://github.com/apple/swift/blob/master/docs/GenericsManifesto.md
    11

    View full-size slide

  12. Conditional2
    Arrayʹ͓͍ͯɺElement͕Equatableͳ৔߹ʹݶΓ
    Conformance
    Array΋Equatableద߹͢Δ
    2 આ໌্ͷҰྫͰ͢
    12

    View full-size slide

  13. TaggedRawValue>
    https://github.com/pointfreeco/swift-tagged
    13

    View full-size slide

  14. use Tagged
    struct User: Decodable, Equatable... {
    typealias Id = Tagged
    let id: Id
    let subscriptionId: Subscription.Id
    }
    struct Subscription: Decodable, Equatable... {
    typealias Id = Tagged
    let id: Id
    }
    14

    View full-size slide

  15. use Tagged
    "Decodable"
    let decoder = JSONDecoder()
    let user = try! decoder.decode(User.self, from: Data(json.utf8))
    "Equatable"
    user1 == user2 // OK
    15

    View full-size slide

  16. https://github.com/pointfreeco/swift-tagged/blob/master/Sources/Tagged/Tagged.swift
    public struct Tagged {
    public var rawValue: RawValue
    public init(rawValue: RawValue) {
    self.rawValue = rawValue
    }
    }
    extension Tagged: RawRepresentable {
    }
    16

    View full-size slide

  17. https://github.com/pointfreeco/swift-tagged/blob/master/Sources/Tagged/Tagged.swift
    extension Tagged: Comparable where RawValue: Comparable {
    extension Tagged: Decodable where RawValue: Decodable {
    extension Tagged: Encodable where RawValue: Encodable {
    extension Tagged: Hashable where RawValue: Hashable {
    extension Tagged: Numeric where RawValue: Numeric {
    extension Tagged: ExpressibleByStringLiteral where RawValue: ExpressibleByStringLiteral {
    ...
    17

    View full-size slide

  18. Conclusion
    • Swift 4.1 Conditional Conformance ʹΑΓܕͷදݱྗ͕๛
    ͔ʹͳͬͨ
    • Tagged Λ࢖͏͜ͱͰϓϦϛςΟϒ3ͳܕΛ؆୯ʹܕԽ͢Δ͜
    ͱ͕Ͱ͖Δ
    3 ೚ҙͷܕͰߏΘͳ͍͕ຊεϥΠυͷྫʹԊͬͯ͜ͷΑ͏ʹදݱ͍ͯ͠Δ
    18

    View full-size slide

  19. SeeAlso
    • Swift 4.1ͷConditional ConformanceͱδΣωϦΫεͷະདྷ
    • https://twitter.com/koher/status/985127876507860993
    • Conditional Conformance in the Standard Library
    • https://swift.org/blog/conditional-conformance/
    19

    View full-size slide