Alexander Voronov
September 15, 2015
1.1k

# Alexander Voronov

Swift: Going Functional

## Alexander Voronov

September 15, 2015

## Transcript

functions
7. ### Functional Programming • Higher-order functions • Immutable states & pure

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

functions • Modularity • Types

14. ### Swift Power • First Class Functions • Currying • Generics

• Type Inference
15. ### Swift Power • First Class Functions • Currying • Generics

• Type Inference • Enums
16. ### First Class Functions func add(x: Int) -> Int -> Int

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

x + 2 } (1...5).map(addTwo) // [3, 4, 5, 6, 7]
18. ### 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]
19. ### Currying func curry<A, B, C>(f: (A, B) -> C) ->

A -> B -> C { return { a in { b in f(a, b) } } }
20. ### Generics func printEach<T: SequenceType>(items: T) { for item in items

{ print(item) } } printEach(1...5) printEach(["one", "two", "three"])
21. ### Type Inference let x = 42.0 x.dynamicType // Double x

is Double // true
22. ### Type Inference var xs = [1, 5, 2, 4, 3]

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

xs.sort(<) print(xs) // [1, 2, 3, 4, 5]
24. ### 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]
25. ### 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]
26. ### Enumerations enum Fruit: String { case Apple = "apple" case

Banana = "banana" case Cherry = "cherry" } Fruit.Apple.rawValue // "apple"

28. ### 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
29. ### Optionals enum Optional<T> { case None case Some(T) } var

x = 5 x = nil // Error!
30. ### 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
31. ### 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

33. None

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

// == 5 let y = Optional(2)
36. ### Functors let y = Optional(2) y + 3 // Error!

// Value of optional type // Optional<Int> not unwrapped
37. ### Functors let y = Optional(2) y.map { \$0 + 3

} // Optional(5)
38. ### Functors func map<U>(f: T -> U) -> U? { switch

self { case .Some(let x): return f(x) case .None: return .None } }
39. ### Functors infix operator <^> { associativity left } func <^><T,

U>(f: T -> U, a: T?) -> U? { return a.map(f) }
40. ### Functors func <^><T, U>(f: T -> U, a: T?) ->

U? { return a.map(f) } let addOne = { \$0 + 1 } addOne <^> Optional(2) // Optional(3)
41. ### Applicative func apply<U>(f: (T -> U)?) -> U? { switch

f { case .Some(let someF): return self.map(someF) case .None: return .None } }
42. ### Applicatives infix operator <*> { associativity left } func <*><T,

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

U>(f: (T -> U)?, a: T?) -> U? { return a.apply(f) } func add(a: Int)(b: Int) -> Int { return a + b }

48. ### Applicatives add <^> Optional(2) <*> Optional(3) // Optional(5) let a

= add <^> Optional(2) let a: (b: Int) -> Int?
49. ### Monads typealias T = Double let f: T -> T

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

= { \$0 * 2.0 } let g: (T, T) -> T = { \$0 / \$1 } f(g(4, 2))
51. ### 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?
52. ### 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) }

54. ### Monads func flatten<U>(a: U??) -> U? { switch a {

case .Some(let someA): return someA case .None: return .None } }
55. ### Monads func flatMap<U>(f: T -> U?) -> U? { return

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

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

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

flatten(map(f)) } func map<U>(f: T -> U) -> U? func map<U?>(f: T -> U?) -> U??
59. ### Monads infix operator >>- { associativity left } func >>-<T,

U>(a: T?, f: T -> U?) -> U? { return a.flatMap(f) }
60. ### Monads func half(a: Int) -> Int? { return a %

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

2 == 0 ? a / 2 : .None } Optional(8) >>- half >>- half // Optional(2)

63. ### Left Identity Law let f = { Optional(\$0 + 1)

} let a = 1 let x = Optional(a) >>- f let y = f(a) x == y
64. ### Right Identity Law func create<T>(value: T) -> T? { return

Optional(value) } let x = Optional(1) >>- create let y = Optional(1) x == y
65. ### 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
66. ### Recap Functor map<U>(f: T -> U) -> M<U> Applicative apply<U>(f:

M<(T -> U)>) -> M<U> Monad flatMap<U>(f: T -> M<U>) -> M<U>

68. ### Pipes infix operator |> { associativity left } public func

|> <T, U>(x: T, f: T -> U) -> U { return f(x) } let addTwo = { \$0 + 2 } let prodThree = { \$0 * 3 } 5 |> addTwo |> prodThree |> print // 21
69. ### Pipes let transformedX = x |> addTwo |> prodThree |>

increment |> square |> pow VS (pow(square(increment(prodThree(addTwo(x))))))

72. ### Argo Example extension Model: Decodable { static func decode(json: JSON)

-> Decoded<Model> { 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" } }
73. ### Argo Example let entities: [Model]? entities = data?.json() >>- {

\$0["entities"] } >>- decode

75. ### 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