Slide 1

Slide 1 text

Swift Rocks 2! Alexander Voronov iOS Developer @ Stanfy

Slide 2

Slide 2 text

Swift Going Functional

Slide 3

Slide 3 text

What is Functional Programming?

Slide 4

Slide 4 text

Functional Programming

Slide 5

Slide 5 text

Functional Programming • Higher-order functions

Slide 6

Slide 6 text

Functional Programming • Higher-order functions • Immutable states & pure functions

Slide 7

Slide 7 text

Functional Programming • Higher-order functions • Immutable states & pure functions • Modularity

Slide 8

Slide 8 text

Functional Programming • Higher-order functions • Immutable states & pure functions • Modularity • Types

Slide 9

Slide 9 text

Swift Power

Slide 10

Slide 10 text

Swift Power

Slide 11

Slide 11 text

Swift Power • First Class Functions

Slide 12

Slide 12 text

Swift Power • First Class Functions • Currying

Slide 13

Slide 13 text

Swift Power • First Class Functions • Currying • Generics

Slide 14

Slide 14 text

Swift Power • First Class Functions • Currying • Generics • Type Inference

Slide 15

Slide 15 text

Swift Power • First Class Functions • Currying • Generics • Type Inference • Enums

Slide 16

Slide 16 text

First Class Functions func add(x: Int) -> Int -> Int { return { y in y + x } } let addOne = add(1) addOne(2) // 3

Slide 17

Slide 17 text

First Class Functions func addTwo(x: Int) -> Int { return x + 2 } (1...5).map(addTwo) // [3, 4, 5, 6, 7]

Slide 18

Slide 18 text

Currying func add(a: Int)(b: Int) -> Int { return a + b } let addOne = add(1) let xs = 1...5 xs.map(addOne) // [2, 3, 4, 5, 6]

Slide 20

Slide 20 text

Generics func printEach(items: T) { for item in items { print(item) } } printEach(1...5) printEach(["one", "two", "three"])

Slide 21

Slide 21 text

Type Inference let x = 42.0 x.dynamicType // Double x is Double // true

Slide 22

Slide 22 text

Type Inference var xs = [1, 5, 2, 4, 3] xs.sort(<) print(xs) // [1, 2, 3, 4, 5]

Slide 23

Slide 23 text

Type Inference var xs = [1, 5, 2, 4, 3] xs.sort(<) print(xs) // [1, 2, 3, 4, 5]

Slide 24

Slide 24 text

Type Inference let xs = [1, 5, 2, 4, 3] let ys = xs.sorted(<) print(xs) // [1, 5, 2, 4, 3] print(ys) // [1, 2, 3, 4, 5]

Slide 25

Slide 25 text

Type Inference let xs = [1, 5, 2, 4, 3] let ys = xs.sorted(<) print(xs) // [1, 5, 2, 4, 3] print(ys) // [1, 2, 3, 4, 5]

Slide 26

Slide 26 text

Enumerations enum Fruit: String { case Apple = "apple" case Banana = "banana" case Cherry = "cherry" } Fruit.Apple.rawValue // "apple"

Slide 27

Slide 27 text

Enumerations enum ValidationResult { case Valid case NotValid(NSError) }

Slide 28

Slide 28 text

Enumerations enum MyApi { case xAuth(String, String) case GetUser(Int) } extension MyApi: MoyaTarget { var baseURL: NSURL { return NSURL(string: "")! } var path: String { switch self { case .xAuth: return "/authorise" case .GetUser(let id): return "/user/\(id)" } } } https://github.com/Moya/Moya

Slide 29

Slide 29 text

Optionals enum Optional { case None case Some(T) } var x = 5 x = nil // Error!

Slide 30

Slide 30 text

Optional Chaining struct Dog { var name: String } struct Person { var dog: Dog? } let dog = Dog(name: "Dodge") let person = Person(dog: dog) let dogName = person.dog?.name

Slide 31

Slide 31 text

Optional Chaining struct Dog { var name: String } struct Person { var dog: Dog? } let dog = Dog(name: "Dodge") let person = Person(dog: dog) let dogName = person.dog?.name Optional Chaining

Slide 32

Slide 32 text

Functors, Applicatives, Monads

Slide 33

Slide 33 text

No content

Slide 34

Slide 34 text

Functors, Applicatives, Monads let x = 2 x + 3 // == 5

Slide 35

Slide 35 text

Functors, Applicatives, Monads let x = 2 x + 3 // == 5 let y = Optional(2)

Slide 36

Slide 36 text

Functors let y = Optional(2) y + 3 // Error! // Value of optional type // Optional not unwrapped

Slide 37

Slide 37 text

Functors let y = Optional(2) y.map { $0 + 3 } // Optional(5)

Slide 38

Slide 38 text

Functors func map(f: T -> U) -> U? { switch self { case .Some(let x): return f(x) case .None: return .None } }

Slide 39

Slide 39 text

Functors infix operator <^> { associativity left } func <^>(f: T -> U, a: T?) -> U? { return a.map(f) }

Slide 40

Slide 40 text

Functors func <^>(f: T -> U, a: T?) -> U? { return a.map(f) } let addOne = { $0 + 1 } addOne <^> Optional(2) // Optional(3)

Slide 41

Slide 41 text

Applicative func apply(f: (T -> U)?) -> U? { switch f { case .Some(let someF): return self.map(someF) case .None: return .None } }

Slide 42

Slide 42 text

Applicatives infix operator <*> { associativity left } func <*>(f: (T -> U)?, a: T?) -> U? { return a.apply(f) }

Slide 43

Slide 43 text

Applicatives infix operator <*> { associativity left } func <*>(f: (T -> U)?, a: T?) -> U? { return a.apply(f) } func add(a: Int)(b: Int) -> Int { return a + b }

Slide 44

Slide 44 text

Applicatives add <^> Optional(2) <*> Optional(3) // Optional(5)

Slide 45

Slide 45 text

Applicatives add <^> Optional(2) <*> Optional(3) // Optional(5)

Slide 46

Slide 46 text

Applicatives add <^> Optional(2) <*> Optional(3) // Optional(5) let a = add <^> Optional(2)

Slide 47

Slide 47 text

Applicatives add <^> Optional(2) <*> Optional(3) // Optional(5) let a = add <^> Optional(2)

Slide 48

Slide 48 text

Applicatives add <^> Optional(2) <*> Optional(3) // Optional(5) let a = add <^> Optional(2) let a: (b: Int) -> Int?

Slide 49

Slide 49 text

Monads typealias T = Double let f: T -> T = { $0 * 2.0 } let g: (T, T) -> T = { $0 / $1 }

Slide 50

Slide 50 text

Monads typealias T = Double let f: T -> T = { $0 * 2.0 } let g: (T, T) -> T = { $0 / $1 } f(g(4, 2))

Slide 51

Slide 51 text

Monads typealias T = Double let f: T -> T = { $0 * 2.0 } let g: (T, T) -> T = { $0 / $1 } f(g(4, 2)) g: (T, T) -> T?

Slide 52

Slide 52 text

Monads typealias T = Double let f: T -> T = { $0 * 2.0 } let g: (T, T) -> T = { $0 / $1 } f(g(4, 2)) g: (T, T) -> T? g(4, 2) >>- { f($0) }

Slide 53

Slide 53 text

Monads >>- == http://adit.io/posts/2013-04-17-functors,_applicatives,_and_monads_in_pictures.html

Slide 54

Slide 54 text

Monads func flatten(a: U??) -> U? { switch a { case .Some(let someA): return someA case .None: return .None } }

Slide 55

Slide 55 text

Monads func flatMap(f: T -> U?) -> U? { return flatten(map(f)) }

Slide 56

Slide 56 text

Monads func flatMap(f: T -> U?) -> U? { return flatten(map(f)) } func map(f: T -> U) -> U?

Slide 57

Slide 57 text

Monads func flatMap(f: T -> U?) -> U? { return flatten(map(f)) } func map(f: T -> U) -> U?

Slide 58

Slide 58 text

Monads func flatMap(f: T -> U?) -> U? { return flatten(map(f)) } func map(f: T -> U) -> U? func map(f: T -> U?) -> U??

Slide 59

Slide 59 text

Monads infix operator >>- { associativity left } func >>-(a: T?, f: T -> U?) -> U? { return a.flatMap(f) }

Slide 60

Slide 60 text

Monads func half(a: Int) -> Int? { return a % 2 == 0 ? a / 2 : .None }

Slide 61

Slide 61 text

Monads func half(a: Int) -> Int? { return a % 2 == 0 ? a / 2 : .None } Optional(8) >>- half >>- half // Optional(2)

Slide 62

Slide 62 text

Monad Laws • Left Identity • Right Identity • Associativity

Slide 63

Slide 63 text

Left Identity Law let f = { Optional($0 + 1) } let a = 1 let x = Optional(a) >>- f let y = f(a) x == y

Slide 64

Slide 64 text

Right Identity Law func create(value: T) -> T? { return Optional(value) } let x = Optional(1) >>- create let y = Optional(1) x == y

Slide 65

Slide 65 text

Associativity Law let double = { Optional(2 * $0) } let triple = { Optional(3 * $0) } let x = Optional(1) >>- double >>- triple let y = Optional(1) >>- { double($0) >>- triple } let z = { Optional(1) >>- double }() >>- triple x == y y == z

Slide 66

Slide 66 text

Recap Functor map(f: T -> U) -> M Applicative apply(f: M<(T -> U)>) -> M Monad flatMap(f: T -> M) -> M

Slide 67

Slide 67 text

Pipes & Railways @ScottWlaschin

Slide 68

Slide 68 text

Pipes infix operator |> { associativity left } public func |> (x: T, f: T -> U) -> U { return f(x) } let addTwo = { $0 + 2 } let prodThree = { $0 * 3 } 5 |> addTwo |> prodThree |> print // 21

Slide 69

Slide 69 text

Pipes let transformedX = x |> addTwo |> prodThree |> increment |> square |> pow VS (pow(square(increment(prodThree(addTwo(x))))))

Slide 70

Slide 70 text

Railways http://fsharpforfunandprofit.com/posts/recipe-part2/

Slide 71

Slide 71 text

Argo JSON Parser + Argo Runes

Slide 72

Slide 72 text

Argo Example extension Model: Decodable { static func decode(json: JSON) -> Decoded { return Model.create <^> json <| "id" <*> json <| "room" <*> json <| "guest_name" <*> json <| "status" <*> json <| "label" <*> json <|? "user_comment" <*> json <| ["channel", "label"] <*> json <| "severity" <*> json <|| "epochs" <*> json <|| "body" } }

Slide 73

Slide 73 text

Argo Example let entities: [Model]? entities = data?.json() >>- { $0["entities"] } >>- decode

Slide 74

Slide 74 text

Where Next?

Slide 75

Slide 75 text

Where Next • Functors, Applicatives and Monads in Pictures • Railway Oriented Programming • Functional Programming in Swift (Objc.io) • Argo • Swiftz • RxSwift • ReactiveCocoa-3.0 • Haskell, F#, Erlang, Elm

Slide 76

Slide 76 text

Thanks!

Slide 77

Slide 77 text

Comments / Questions? @aleks_voronov a-voronov