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

Alexander Voronov

Alexander Voronov

Swift: Going Functional

D94c9a683d3b45cfe42548cd5a1a39b0?s=128

Alexander Voronov

September 15, 2015
Tweet

Transcript

  1. Swift Rocks 2! Alexander Voronov iOS Developer @ Stanfy

  2. Swift Going Functional

  3. What is Functional Programming?

  4. Functional Programming

  5. Functional Programming • Higher-order functions

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

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

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

    functions • Modularity • Types
  9. Swift Power

  10. Swift Power

  11. Swift Power • First Class Functions

  12. Swift Power • First Class Functions • Currying

  13. Swift Power • First Class Functions • Currying • Generics

  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"
  27. Enumerations enum ValidationResult { case Valid case NotValid(NSError) }

  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
  32. Functors, Applicatives, Monads

  33. None
  34. Functors, Applicatives, Monads let x = 2 x + 3

    // == 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 }
  44. Applicatives add <^> Optional(2) <*> Optional(3) // Optional(5)

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

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

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

    = add <^> Optional(2)
  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) }
  53. Monads >>- == http://adit.io/posts/2013-04-17-functors,_applicatives,_and_monads_in_pictures.html

  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)
  62. Monad Laws • Left Identity • Right Identity • Associativity

  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>
  67. Pipes & Railways @ScottWlaschin

  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))))))
  70. Railways http://fsharpforfunandprofit.com/posts/recipe-part2/

  71. Argo JSON Parser + Argo Runes

  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
  74. Where Next?

  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
  76. Thanks!

  77. Comments / Questions? @aleks_voronov a-voronov