Slide 1

Slide 1 text

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

Slide 2

Slide 2 text

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

Slide 3

Slide 3 text

What’s type class? [email protected]

Slide 4

Slide 4 text

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

Slide 5

Slide 5 text

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]

Slide 6

Slide 6 text

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

Slide 7

Slide 7 text

• 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]

Slide 8

Slide 8 text

• 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]

Slide 9

Slide 9 text

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

Slide 10

Slide 10 text

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

Slide 11

Slide 11 text

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]

Slide 12

Slide 12 text

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]

Slide 13

Slide 13 text

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]

Slide 14

Slide 14 text

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

Slide 15

Slide 15 text

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

Slide 16

Slide 16 text

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]

Slide 17

Slide 17 text

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

Slide 18

Slide 18 text

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

Slide 19

Slide 19 text

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

Slide 20

Slide 20 text

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

Slide 21

Slide 21 text

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

Slide 22

Slide 22 text

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

Slide 23

Slide 23 text

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]

Slide 24

Slide 24 text

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]

Slide 25

Slide 25 text

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

Slide 26

Slide 26 text

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

Slide 27

Slide 27 text

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

Slide 28

Slide 28 text

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

Slide 29

Slide 29 text

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]

Slide 30

Slide 30 text

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]

Slide 31

Slide 31 text

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]

Slide 32

Slide 32 text

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]

Slide 33

Slide 33 text

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

Slide 34

Slide 34 text

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]

Slide 35

Slide 35 text

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