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 [email protected]
  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 [email protected]
  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: ...) [email protected]
  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) [email protected]
  5. Type class in Haskell class Eq a where (==), (/=)

    :: a -> a -> Bool x == y = not (x /= y) x /= y = not (x == y) [email protected]
  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 [email protected]
  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) } [email protected]
  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 } } [email protected]
  9. Type class in Swift protocol Eq { func equalTo(other: Self)

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

    -> Bool } extension Int : Eq { func equalTo(other: Int) -> Bool { return self == other } } [email protected]
  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 [email protected]
  12. Swift: Equtable protocol Equatable { func == (lhs: Self, rhs:

    Self) -> Bool } func != <T : Equatable>(lhs: T, rhs: T) -> Bool { return !(lhs == rhs) } [email protected]
  13. Swift: Equtable extension CGPoint : Equatable {} public func ==

    (lhs: CGPoint, rhs: CGPoint) -> Bool { return lhs.x == rhs.x && lhs.y == rhs.y } [email protected]
  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 [email protected]
  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 [email protected]
  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 [email protected]
  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 [email protected]
  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 [email protected]
  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 [email protected]
  20. 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]