$30 off During Our Annual Pro Sale. View Details »

Type classes in Swift

Type classes in Swift

Type class design pattern in Swift

Kishikawa Katsumi

July 16, 2016
Tweet

More Decks by Kishikawa Katsumi

Other Decks in Programming

Transcript

  1. Type classes in Swift
    ܕΫϥεษڧձ
    Katsumi Kishikawa
    [email protected]

    View Slide

  2. Katsumi Kishikawa
    Realm Inc.
    [email protected]
    github.com/kishikawakatsumi

    View Slide

  3. What’s type class?
    [email protected]

    View Slide

  4. In computer science, a type class
    is a type system construct that
    supports ad hoc polymorphism.
    Wikipedia
    Type class
    [email protected]

    View Slide

  5. In programming languages and type theory,
    polymorphism is the provision of a single interface
    to entities of different types. A polymorphic type
    is one whose operations can also be applied to
    values of some other type, or types.
    Wikipedia
    Polymorphism
    [email protected]

    View Slide

  6. • Subtype Polymorphism
    • Parameteric Polymorphism
    • Ad-hoc Polymorphism
    Polymorphism
    [email protected]

    View Slide

  7. • Subtype Polymorphism => Subclassing
    • Parameteric Polymorphism
    • Ad-hoc Polymorphism
    Polymorphism
    let button: UIControl = UIButton()
    let slider: UIControl = UISlider()
    button.addTarget(self, action: ..., forControlEvents: ...)
    slider.addTarget(self, action: ..., forControlEvents: ...)
    [email protected]

    View Slide

  8. • Subtype Polymorphism
    • Parameteric Polymorphism => Generics
    • Ad-hoc Polymorphism
    Polymorphism
    let x: Int = 0, y: Int = 1
    let x: Double = 0.0, y: Double = 1.0
    min(x, y)
    [email protected]

    View Slide

  9. • Subtype Polymorphism
    • Parameteric Polymorphism
    • Ad-hoc Polymorphism => Overloading, Type class
    Polymorphism
    [email protected]

    View Slide

  10. Type class in Haskell
    class Eq a where
    (==), (/=) :: a -> a -> Bool
    x == y = not (x /= y)
    x /= y = not (x == y)
    [email protected]

    View Slide

  11. Type class in Haskell
    class Eq a where
    (==), (/=) :: a -> a -> Bool
    x == y = not (x /= y)
    x /= y = not (x == y)
    instance Eq Integer class
    x == y = x `integerEq` y
    [email protected]

    View Slide

  12. Type class in Scala
    trait Eq[A]
    def equal(x: A, y: A): Boolean
    def notEqual(x: A, y: A): Boolean = !equal(x, y)
    }
    [email protected]

    View Slide

  13. Type class in Swift
    protocol Eq {
    associatedtype T
    func equalTo(other: T) -> Bool
    }
    extension Int : Eq {
    typealias T = Int
    func equalTo(other: T) -> Bool {
    return self == other
    }
    }
    [email protected]

    View Slide

  14. Type class in Swift
    protocol Eq {
    func equalTo(other: Self) -> Bool
    }
    extension Int : Eq {
    func equalTo(other: Int) -> Bool {
    return self == other
    }
    }
    [email protected]

    View Slide

  15. Type class in Swift
    protocol Eq {
    func equalTo(other: Self) -> Bool
    }
    extension Int : Eq {
    func equalTo(other: Int) -> Bool {
    return self == other
    }
    }
    [email protected]

    View Slide

  16. Type class in Swift
    protocol Eq {
    func equalTo(other: Self) -> Bool
    }
    extension Int : Eq {
    func equalTo(other: Int) -> Bool {
    return self == other
    }
    }
    let i = 1
    let j = 1
    print(i.equalTo(j)) // => true
    [email protected]

    View Slide

  17. Swift: Equtable
    protocol Equatable {
    func == (lhs: Self, rhs: Self) -> Bool
    }
    func != (lhs: T, rhs: T) -> Bool {
    return !(lhs == rhs)
    }
    [email protected]

    View Slide

  18. Swift: Equtable
    extension CGPoint : Equatable {}
    public func == (lhs: CGPoint, rhs: CGPoint) -> Bool {
    return lhs.x == rhs.x && lhs.y == rhs.y
    }
    [email protected]

    View Slide

  19. • ܕΫϥεͱ͸ҟͳΔܕʹରͯ͠ಛఆͷৼΔ෣͍ʹ
    ద߹ͤ͞ΔσβΠϯύλʔϯ
    • طଘͷܕʹରͯ͠ػೳΛ௥Ճ͢Δ͜ͱ͕Ͱ͖Δ
    • Կ͕࢖ΘΕΔ͔͸ίϯύΠϧ࣌ʹܾఆ͢Δ
    • Swiftඪ४ϥΠϒϥϦͰ΋࢖ΘΕ͍ͯΔύλʔϯ
    Short summary
    [email protected]

    View Slide

  20. Example: Caesar cipher
    class Ceasarable c where
    toCeasar :: c -> String
    [email protected]

    View Slide

  21. trait Ceasarable[T] {
    def toCeasar(input: T): String
    }
    Example: Caesar cipher
    [email protected]

    View Slide

  22. protocol Ceasarable {
    associatedtype T
    static func toCeasar(input: T) -> String
    }
    Example: Caesar cipher
    [email protected]

    View Slide

  23. extension Int : Ceasarable {
    typealias T = Int
    static func toCeasar(input: T) -> String {
    return "\(input)".unicodeScalars.reduce("") {
    (acc, char) in
    return acc + String(UnicodeScalar(char.value + 3))
    }
    }
    }
    extension String : Ceasarable {
    typealias T = String
    static func toCeasar(input: String) -> String {
    return input.unicodeScalars.reduce("") {
    (acc, char) in
    return acc + String(UnicodeScalar(char.value + 3))
    }
    }
    }
    Example: Caesar cipher
    [email protected]

    View Slide

  24. func encodeInCeasar(c: C.T) -> String {
    return C.toCeasar(c)
    }
    print(encodeInCeasar(1234)) //=> 4567
    print(encodeInCeasar("abcd")) //=> defg
    print(encodeInCeasar(1.234))
    //=> Cannot invoke 'encodeInCeasar' with an argument list of type '(Double)'
    Example: Caesar cipher
    [email protected]

    View Slide

  25. protocol Ceasarable {
    associatedtype T
    static func toCeasar(input: T) -> String
    }
    Example: Caesar cipher
    [email protected]

    View Slide

  26. protocol Ceasarable {
    associatedtype T
    static func toCeasar(input: T) -> String
    }
    Example: Caesar cipher
    [email protected]

    View Slide

  27. protocol Ceasarable {
    static func toCeasar(input: Self) -> String
    }
    Example: Caesar cipher
    [email protected]

    View Slide

  28. protocol Ceasarable {
    static func toCeasar(input: Self) -> String
    }
    Example: Caesar cipher
    [email protected]

    View Slide

  29. extension Int : Ceasarable {
    static func toCeasar(input: Int) -> String {
    return "\(input)".unicodeScalars.reduce("") {
    (acc, char) in
    return acc + String(UnicodeScalar(char.value + 3))
    }
    }
    }
    extension String : Ceasarable {
    static func toCeasar(input: String) -> String {
    return input.unicodeScalars.reduce("") {
    (acc, char) in
    return acc + String(UnicodeScalar(char.value + 3))
    }
    }
    }
    Example: Caesar cipher
    [email protected]

    View Slide

  30. extension Int : Ceasarable {
    static func toCeasar(input: Int) -> String {
    return "\(input)".unicodeScalars.reduce("") {
    (acc, char) in
    return acc + String(UnicodeScalar(char.value + 3))
    }
    }
    }
    extension String : Ceasarable {
    static func toCeasar(input: String) -> String {
    return input.unicodeScalars.reduce("") {
    (acc, char) in
    return acc + String(UnicodeScalar(char.value + 3))
    }
    }
    }
    Example: Caesar cipher
    [email protected]

    View Slide

  31. func encodeInCeasar(c: C) -> String {
    return C.toCeasar(c)
    }
    print(encodeInCeasar(1234)) //=> 4567
    print(encodeInCeasar("abcd")) //=> defg
    print(encodeInCeasar(1.234))
    //=> Cannot invoke 'encodeInCeasar' with an argument list of type '(Double)'
    Example: Caesar cipher
    [email protected]

    View Slide

  32. protocol Ceasarable {
    static func toCeasar(input: Self) -> String
    }
    extension Int : Ceasarable {
    static func toCeasar(input: Int) -> String {
    ...
    }
    }
    extension String : Ceasarable {
    static func toCeasar(input: String) -> String {
    ...
    }
    }
    print(encodeInCeasar(1234)) //=> 4567
    print(encodeInCeasar("abcd")) //=> defg
    Example: Caesar cipher
    [email protected]

    View Slide

  33. Recap
    • Swiftʹ͓͚ΔܕΫϥε͸ProtocolͱExtensionΛ࢖ͬͨσβΠϯύλʔϯ
    • ʢܕΫϥεͱ໌ࣔ͞Εͯ͸͍ͳ͍͕ʣඪ४ϥΠϒϥϦͳͲͰࣗવʹ࢖Θ
    Ε͍ͯΔ
    • ܕΫϥε͸ҟͳΔܕʹର͢Δڞ௨ͷৼΔ෣͍Λఏڙ͠ɺඞཁʹԠͯ͡ܕ
    ͕ͦΕΛ࢖͑ΔΑ͏ʹ͢Δ࢓૊Έ
    • Կ͕࢖ΘΕΔ͔͸ίϯύΠϧ࣌ʹܾఆ͢Δ
    • ܧঝΛ࢖ΘͣʹػೳΛ௥Ճͨ͠Γ૊Έ߹ΘͤΔ͜ͱ͕Ͱ͖Δ
    • ܧঝʹΑ࣮ͬͯݱ͢Δํ๏ʹൺ΂ͯΑΓॊೈʹܕΛ֦ுͰ͖Δ
    [email protected]

    View Slide

  34. References
    • WWDC 2015 session “Protocol-Oriented Programming in Swift”
    https://developer.apple.com/videos/play/wwdc2015/408/
    • Typeclasses in Swift, Haskell and Scala
    https://touk.pl/blog/2015/09/14/typeclasses-in-swift/
    • Typeclass in Swift and Scala
    http://www.danishin.com/article/Typeclass_in_Swift_and_Scala
    • Associated types vs. type parameters - reason for the former?
    https://devforums.apple.com/thread/230611
    • Swift Generic Protocols
    https://milen.me/writings/swift-generic-protocols/
    • Swift: Associated Types
    http://www.russbishop.net/swift-associated-types
    [email protected]

    View Slide

  35. Questions?
    Katsuma Kishikawa
    [email protected]
    www.realm.io/jp
    @k_katsumi

    View Slide