stanfy madcode meetup #9: functional programming 101 with swift

78
Stanfy MadCode #9 Alexander Voronov iOS Developer @ Stanfy https://www.facebook.com/MadCodeMeetup

Upload: stanfy

Post on 22-Jan-2018

319 views

Category:

Mobile


1 download

TRANSCRIPT

Page 1: Stanfy MadCode Meetup #9: Functional Programming 101 with Swift

Stanfy MadCode #9

Alexander Voronov iOS Developer @ Stanfy

https://www.facebook.com/MadCodeMeetup

Page 2: Stanfy MadCode Meetup #9: Functional Programming 101 with Swift

Functional Programming 101

With Swift

Page 3: Stanfy MadCode Meetup #9: Functional Programming 101 with Swift

What is Functional Programming?

Page 4: Stanfy MadCode Meetup #9: Functional Programming 101 with Swift

Functional Programming• Higher-order functions

Page 5: Stanfy MadCode Meetup #9: Functional Programming 101 with Swift

Functional Programming• Higher-order functions

• Immutable states & pure functions

Page 6: Stanfy MadCode Meetup #9: Functional Programming 101 with Swift

Functional Programming• Higher-order functions

• Immutable states & pure functions

• Declarative

Page 7: Stanfy MadCode Meetup #9: Functional Programming 101 with Swift

Functional Programming• Higher-order functions

• Immutable states & pure functions

• Declarative

• Modularity

Page 8: Stanfy MadCode Meetup #9: Functional Programming 101 with Swift

Functional Programming• Higher-order functions

• Immutable states & pure functions

• Declarative

• Modularity

• Types

Page 9: Stanfy MadCode Meetup #9: Functional Programming 101 with Swift

Swift Power

Page 10: Stanfy MadCode Meetup #9: Functional Programming 101 with Swift

Swift Power• First Class Functions

Page 11: Stanfy MadCode Meetup #9: Functional Programming 101 with Swift

Swift Power• First Class Functions

• Currying

Page 12: Stanfy MadCode Meetup #9: Functional Programming 101 with Swift

Swift Power• First Class Functions

• Currying

• Generics

Page 13: Stanfy MadCode Meetup #9: Functional Programming 101 with Swift

Swift Power• First Class Functions

• Currying

• Generics

• Type Inference

Page 14: Stanfy MadCode Meetup #9: Functional Programming 101 with Swift

Swift Power• First Class Functions

• Currying

• Generics

• Type Inference

• Enums

Page 15: Stanfy MadCode Meetup #9: Functional Programming 101 with Swift

First Class Functionsfunc add(x: Int) -> Int -> Int { return { y in y + x } }

let addOne = add(1) addOne(2)

// 3

Page 16: Stanfy MadCode Meetup #9: Functional Programming 101 with Swift

First Class Functionsfunc addTwo(x: Int) -> Int { return x + 2 }

(1...5).map(addTwo)

// [3, 4, 5, 6, 7]

Page 17: Stanfy MadCode Meetup #9: Functional Programming 101 with Swift

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

Page 18: Stanfy MadCode Meetup #9: Functional Programming 101 with Swift

Currying

func curry<A, B, C>(f: (A, B) -> C) -> A -> B -> C {

return { a in { b in f(a, b) } } }

Page 19: Stanfy MadCode Meetup #9: Functional Programming 101 with Swift

Generics

func printEach<T: SequenceType>(items: T) { for item in items { print(item) } }

printEach(1...5) printEach(["one", "two", "three"])

Page 20: Stanfy MadCode Meetup #9: Functional Programming 101 with Swift

Type Inference

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

Page 21: Stanfy MadCode Meetup #9: Functional Programming 101 with Swift

Type Inference

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

Page 22: Stanfy MadCode Meetup #9: Functional Programming 101 with Swift

Type Inference

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

Page 23: Stanfy MadCode Meetup #9: Functional Programming 101 with Swift

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]

Page 24: Stanfy MadCode Meetup #9: Functional Programming 101 with Swift

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]

Page 25: Stanfy MadCode Meetup #9: Functional Programming 101 with Swift

Enumerationsenum Fruit: String { case Apple = "apple" case Banana = "banana" case Cherry = "cherry" }

Fruit.Apple.rawValue // "apple"

Page 26: Stanfy MadCode Meetup #9: Functional Programming 101 with Swift

Enumerations

enum ValidationResult { case Valid case NotValid(NSError) }

Page 27: Stanfy MadCode Meetup #9: Functional Programming 101 with Swift

Enumerationsenum 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

Page 28: Stanfy MadCode Meetup #9: Functional Programming 101 with Swift

Optionalsenum Optional<T> { case None case Some(T) }

var x = 5 x = nil // Error!

Page 29: Stanfy MadCode Meetup #9: Functional Programming 101 with Swift

Optional Chainingstruct Dog { var name: String } struct Person { var dog: Dog? }

let dog = Dog(name: "Dodge") let person = Person(dog: dog) let dogName = person.dog?.name

Page 30: Stanfy MadCode Meetup #9: Functional Programming 101 with Swift

Optional Chainingstruct 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

Page 31: Stanfy MadCode Meetup #9: Functional Programming 101 with Swift

Functors, Applicatives,

Monads

Page 32: Stanfy MadCode Meetup #9: Functional Programming 101 with Swift
Page 33: Stanfy MadCode Meetup #9: Functional Programming 101 with Swift

Functors, Applicatives, Monads

let x = 2 x + 3 // == 5

Page 34: Stanfy MadCode Meetup #9: Functional Programming 101 with Swift

Functors, Applicatives, Monads

let x = 2 x + 3 // == 5

let y = Optional(2)

Page 35: Stanfy MadCode Meetup #9: Functional Programming 101 with Swift

Functors

let y = Optional(2) y + 3

// Error! // Value of optional type // Optional<Int> not unwrapped

Page 36: Stanfy MadCode Meetup #9: Functional Programming 101 with Swift

Functors

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

// Optional(5)

Page 37: Stanfy MadCode Meetup #9: Functional Programming 101 with Swift

Definition

Optional<T> == T?

Page 38: Stanfy MadCode Meetup #9: Functional Programming 101 with Swift

Functors

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

Page 39: Stanfy MadCode Meetup #9: Functional Programming 101 with Swift

Functors

infix operator <^> { associativity left

}

func <^> <T, U>(f: T -> U, a: Optional<T>) -> Optional<U> { return a.map(f) }

Page 40: Stanfy MadCode Meetup #9: Functional Programming 101 with Swift

Functors

func <^><T, U>(f: T -> U, a: Optional<T>) -> Optional<U> { return a.map(f) }

let addOne = { $0 + 1 }

addOne <^> Optional(2) // Optional(3)

Page 41: Stanfy MadCode Meetup #9: Functional Programming 101 with Swift

Functors

func <^><T, U>(f: T -> U, a: Optional<T>) -> Optional<U> { return a.map(f) }

let addOne = { $0 + 1 }

addOne <^> Optional(2) // Optional(3)

add <^> Optional(2) <^> Optional(3)

Page 42: Stanfy MadCode Meetup #9: Functional Programming 101 with Swift

Functors

func <^><T, U>(f: T -> U, a: Optional<T>) -> Optional<U> { return a.map(f) }

let addOne = { $0 + 1 }

addOne <^> Optional(2) // Optional(3)

add <^> Optional(2) <^> Optional(3)

Page 43: Stanfy MadCode Meetup #9: Functional Programming 101 with Swift

Applicative

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

Page 44: Stanfy MadCode Meetup #9: Functional Programming 101 with Swift

Applicatives

infix operator <*> { associativity left }

func <*><T, U>(f: Optional<(T -> U)>, a: Optional<T>) -> Optional<U> { return a.apply(f) }

Page 45: Stanfy MadCode Meetup #9: Functional Programming 101 with Swift

Applicatives

infix operator <*> { associativity left }

func <*><T, U>(f: Optional<(T -> U)>, a: Optional<T>) -> Optional<U> { return a.apply(f) }

func add(a: Int)(b: Int) -> Int { return a + b }

Page 46: Stanfy MadCode Meetup #9: Functional Programming 101 with Swift

Applicatives

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

Page 47: Stanfy MadCode Meetup #9: Functional Programming 101 with Swift

Applicatives

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

let a = add <^> Optional(2)

Page 48: Stanfy MadCode Meetup #9: Functional Programming 101 with Swift

Applicatives

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

let a = add <^> Optional(2)

let a: (b: Int) -> Optional<Int>

Page 49: Stanfy MadCode Meetup #9: Functional Programming 101 with Swift

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

Page 50: Stanfy MadCode Meetup #9: Functional Programming 101 with Swift

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

f(g(4, 2))

Page 51: Stanfy MadCode Meetup #9: Functional Programming 101 with Swift

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

f(g(4, 2))

g: (T, T) -> Optional<T>

Page 52: Stanfy MadCode Meetup #9: Functional Programming 101 with Swift

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

f(g(4, 2))

g: (T, T) -> Optional<T>

g(4, 2) >>- { f($0) }

Page 53: Stanfy MadCode Meetup #9: Functional Programming 101 with Swift

Monads

>>-==

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

Page 54: Stanfy MadCode Meetup #9: Functional Programming 101 with Swift

Monads

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

Page 55: Stanfy MadCode Meetup #9: Functional Programming 101 with Swift

Monadsfunc flatMap<U>(f: T -> Optional<U>) -> Optional<U> { return flatten(map(f)) }

Page 56: Stanfy MadCode Meetup #9: Functional Programming 101 with Swift

Monadsfunc flatMap<U>(f: T -> Optional<U>) -> Optional<U> { return flatten(map(f)) }

func map<U>(f: T -> U) -> Optional<U>

Page 57: Stanfy MadCode Meetup #9: Functional Programming 101 with Swift

Monadsfunc flatMap<U>(f: T -> Optional<U>) -> Optional<U> { return flatten(map(f)) }

func map<U>(f: T -> U) -> Optional<U>

Page 58: Stanfy MadCode Meetup #9: Functional Programming 101 with Swift

Monadsfunc flatMap<U>(f: T -> Optional<U>) -> Optional<U> { return flatten(map(f)) }

func map<U>(f: T -> U) -> Optional<U>

func map<Optional<U>>(f: T -> Optional<U>) -> Optional<Optional<U>>

Page 59: Stanfy MadCode Meetup #9: Functional Programming 101 with Swift

Monads

infix operator >>- { associativity left }

func >>-<T, U>(a: Optional<T>, f: T -> Optional<U>) -> Optional<U> { return a.flatMap(f) }

Page 60: Stanfy MadCode Meetup #9: Functional Programming 101 with Swift

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

Page 61: Stanfy MadCode Meetup #9: Functional Programming 101 with Swift

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

Optional(8) >>- half >>- half // Optional(2)

Page 62: Stanfy MadCode Meetup #9: Functional Programming 101 with Swift

Monad Laws

• Left Identity

• Right Identity

• Associativity

Page 63: Stanfy MadCode Meetup #9: Functional Programming 101 with Swift

Left Identity Lawlet f = { Optional($0 + 1) } let a = 1

let x = Optional(a) >>- f let y = f(a)

x == y

Page 64: Stanfy MadCode Meetup #9: Functional Programming 101 with Swift

Right Identity Law

func create<T>(value: T) -> Optional<T> { return Optional(value) }

let x = Optional(1) >>- create let y = Optional(1)

x == y

Page 65: Stanfy MadCode Meetup #9: Functional Programming 101 with Swift

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

Page 66: Stanfy MadCode Meetup #9: Functional Programming 101 with Swift

RecapFunctor 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>

Page 67: Stanfy MadCode Meetup #9: Functional Programming 101 with Swift

Pipes & Railways

@ScottWlaschin

Page 68: Stanfy MadCode Meetup #9: Functional Programming 101 with Swift

Pipesinfix 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

Page 69: Stanfy MadCode Meetup #9: Functional Programming 101 with Swift

Pipeslet transformedX = x |> addTwo |> prodThree |> increment |> square |> pow

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

Page 70: Stanfy MadCode Meetup #9: Functional Programming 101 with Swift

Railways

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

Page 71: Stanfy MadCode Meetup #9: Functional Programming 101 with Swift

Argo JSON Parser

+

Argo Runes

Page 72: Stanfy MadCode Meetup #9: Functional Programming 101 with Swift

Argo Exampleextension 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" } }

Page 73: Stanfy MadCode Meetup #9: Functional Programming 101 with Swift

Argo Example

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

Page 74: Stanfy MadCode Meetup #9: Functional Programming 101 with Swift

ReactiveCocoa Example

valueLabel.rac_text <~ viewModel.selectedIndex.producer |> ignoreNil |> combineLatestWith(viewModel.items.producer) |> filter { index, items in index < items.count } |> map { index, items in items[index] }

Page 75: Stanfy MadCode Meetup #9: Functional Programming 101 with Swift

Where Next?

Page 76: Stanfy MadCode Meetup #9: Functional Programming 101 with Swift

elm-lang.or

gwww.erlan

g.orgfsharp.org

https://www.haskell.or

g

https://github.com/ReactiveCocoa/ReactiveCocoa

https://github.com/ReactiveX/RxSwift

https://github.com/typelift/Swiftz

https://github.com/

thoughtbot/Argo

www.objc.io/books/fpinswift/fsharpforfunandprofit.com/posts/recipe-part2/

adit.io/posts/2013-04-17-functors,_applicatives,_and_monads_in_pictures.html

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

Page 77: Stanfy MadCode Meetup #9: Functional Programming 101 with Swift

Thanks!

Page 78: Stanfy MadCode Meetup #9: Functional Programming 101 with Swift

Comments / Questions?

@aleks_voronova-voronov