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

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. In computer science, a type class is a type system

    construct that supports ad hoc polymorphism. Wikipedia Type class kk@realm.io
  2. 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 kk@realm.io
  3. • 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: ...) kk@realm.io
  4. • 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) kk@realm.io
  5. Type class in Haskell class Eq a where (==), (/=)

    :: a -> a -> Bool x == y = not (x /= y) x /= y = not (x == y) kk@realm.io
  6. 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 kk@realm.io
  7. Type class in Scala trait Eq[A] def equal(x: A, y:

    A): Boolean def notEqual(x: A, y: A): Boolean = !equal(x, y) } kk@realm.io
  8. 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 } } kk@realm.io
  9. Type class in Swift protocol Eq { func equalTo(other: Self)

    -> Bool } extension Int : Eq { func equalTo(other: Int) -> Bool { return self == other } } kk@realm.io
  10. Type class in Swift protocol Eq { func equalTo(other: Self)

    -> Bool } extension Int : Eq { func equalTo(other: Int) -> Bool { return self == other } } kk@realm.io
  11. 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 kk@realm.io
  12. Swift: Equtable protocol Equatable { func == (lhs: Self, rhs:

    Self) -> Bool } func != <T : Equatable>(lhs: T, rhs: T) -> Bool { return !(lhs == rhs) } kk@realm.io
  13. Swift: Equtable extension CGPoint : Equatable {} public func ==

    (lhs: CGPoint, rhs: CGPoint) -> Bool { return lhs.x == rhs.x && lhs.y == rhs.y } kk@realm.io
  14. 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 kk@realm.io
  15. func encodeInCeasar<C: Ceasarable where C.T == C>(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 kk@realm.io
  16. 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 kk@realm.io
  17. 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 kk@realm.io
  18. func encodeInCeasar<C: Ceasarable>(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 kk@realm.io
  19. 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 kk@realm.io
  20. Recap • Swiftʹ͓͚ΔܕΫϥε͸ProtocolͱExtensionΛ࢖ͬͨσβΠϯύλʔϯ • ʢܕΫϥεͱ໌ࣔ͞Εͯ͸͍ͳ͍͕ʣඪ४ϥΠϒϥϦͳͲͰࣗવʹ࢖Θ Ε͍ͯΔ • ܕΫϥε͸ҟͳΔܕʹର͢Δڞ௨ͷৼΔ෣͍Λఏڙ͠ɺඞཁʹԠͯ͡ܕ ͕ͦΕΛ࢖͑ΔΑ͏ʹ͢Δ࢓૊Έ •

    Կ͕࢖ΘΕΔ͔͸ίϯύΠϧ࣌ʹܾఆ͢Δ • ܧঝΛ࢖ΘͣʹػೳΛ௥Ճͨ͠Γ૊Έ߹ΘͤΔ͜ͱ͕Ͱ͖Δ • ܧঝʹΑ࣮ͬͯݱ͢Δํ๏ʹൺ΂ͯΑΓॊೈʹܕΛ֦ுͰ͖Δ kk@realm.io
  21. 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 kk@realm.io