Upgrade to Pro
— share decks privately, control downloads, hide ads and more …
Speaker Deck
Features
Speaker Deck
PRO
Sign in
Sign up for free
Search
Search
Alexander Voronov
Search
Oleksandr Voronov
September 15, 2015
Programming
2
1.2k
Alexander Voronov
Swift: Going Functional
https://youtu.be/Dc9aKhs37BE
Oleksandr Voronov
September 15, 2015
Tweet
Share
More Decks by Oleksandr Voronov
See All by Oleksandr Voronov
Controllable Randomness in Unit Tests
alexandervoronov
1
30
Modularizing your iOS apps
alexandervoronov
0
93
TDD in Real World
alexandervoronov
1
200
Building CLI with Swift
alexandervoronov
1
310
Stanfy MadCode 10: From Java to Kotlin, from Objective-C to Swift
alexandervoronov
0
200
ReactiveCocoa
alexandervoronov
0
120
Other Decks in Programming
See All in Programming
[技育CAMPアカデミア]アイディアを形に!【超入門】スマホアプリ開発〜リリースまでの流れをご紹介
teamlab
PRO
0
350
Semantic search with Django and pgvector
pauloxnet
0
240
Tailwind CSSを本気でカスタマイズする方法
fsubal
2
280
スクラムチームと認知負荷 - ニフティのスクラムトーク Vol2. / NIFTY Tech Talk #18
niftycorp
PRO
1
120
チーム力を高めるスクラム実践法:カンバン公開と課題攻略について - ニフティのスクラムトーク Vol. 2 - NIFTY Tech Talk #18
niftycorp
PRO
1
110
SpringBoot+MyBatisで例外が出たときどこを見るか
syukai
0
110
SwiftUI Performance 不要なViewの再描画と更新を抑える
bigamitiongit
1
160
甘い香りに誘われてVanilla Extractを1年間運用してみた
miyahkun
1
110
[SF Ruby, March 2024] Rails on Wasm
palkan
0
380
FigmaとPHPで作る1ミリたりとも表示崩れしない最強の帳票印刷ソリューション
ttskch
39
18k
スクラムガイドのスプリントレトロスペクティブを改めて読みかえしてみた / Re-reading the Sprint Retrospective Section in the Scrum Guide
mackey0225
3
330
Rubyでたのしむクリエイティブコーディング/Enjoy Creative coding with Ruby
chobishiba
1
160
Featured
See All Featured
Web development in the modern age
philhawksworth
202
10k
[Rails World 2023 - Day 1 Closing Keynote] - The Magic of Rails
eileencodes
1
1.3k
Principles of Awesome APIs and How to Build Them.
keavy
120
16k
Java REST API Framework Comparison - PWX 2021
mraible
PRO
18
6.9k
Six Lessons from altMBA
skipperchong
20
3k
Designing for Performance
lara
601
67k
Happy Clients
brianwarren
91
6.4k
Fashionably flexible responsive web design (full day workshop)
malarkey
397
65k
Why You Should Never Use an ORM
jnunemaker
PRO
50
8.6k
StorybookのUI Testing Handbookを読んだ
zakiyama
11
4.6k
Side Projects
sachag
451
41k
From Idea to $5000 a Month in 5 Months
shpigford
377
45k
Transcript
Swift Rocks 2! Alexander Voronov iOS Developer @ Stanfy
Swift Going Functional
What is Functional Programming?
Functional Programming
Functional Programming • Higher-order functions
Functional Programming • Higher-order functions • Immutable states & pure
functions
Functional Programming • Higher-order functions • Immutable states & pure
functions • Modularity
Functional Programming • Higher-order functions • Immutable states & pure
functions • Modularity • Types
Swift Power
Swift Power
Swift Power • First Class Functions
Swift Power • First Class Functions • Currying
Swift Power • First Class Functions • Currying • Generics
Swift Power • First Class Functions • Currying • Generics
• Type Inference
Swift Power • First Class Functions • Currying • Generics
• Type Inference • Enums
First Class Functions func add(x: Int) -> Int -> Int
{ return { y in y + x } } let addOne = add(1) addOne(2) // 3
First Class Functions func addTwo(x: Int) -> Int { return
x + 2 } (1...5).map(addTwo) // [3, 4, 5, 6, 7]
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]
Currying func curry<A, B, C>(f: (A, B) -> C) ->
A -> B -> C { return { a in { b in f(a, b) } } }
Generics func printEach<T: SequenceType>(items: T) { for item in items
{ print(item) } } printEach(1...5) printEach(["one", "two", "three"])
Type Inference let x = 42.0 x.dynamicType // Double x
is Double // true
Type Inference var xs = [1, 5, 2, 4, 3]
xs.sort(<) print(xs) // [1, 2, 3, 4, 5]
Type Inference var xs = [1, 5, 2, 4, 3]
xs.sort(<) print(xs) // [1, 2, 3, 4, 5]
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]
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]
Enumerations enum Fruit: String { case Apple = "apple" case
Banana = "banana" case Cherry = "cherry" } Fruit.Apple.rawValue // "apple"
Enumerations enum ValidationResult { case Valid case NotValid(NSError) }
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
Optionals enum Optional<T> { case None case Some(T) } var
x = 5 x = nil // Error!
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 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
Functors, Applicatives, Monads
None
Functors, Applicatives, Monads let x = 2 x + 3
// == 5
Functors, Applicatives, Monads let x = 2 x + 3
// == 5 let y = Optional(2)
Functors let y = Optional(2) y + 3 // Error!
// Value of optional type // Optional<Int> not unwrapped
Functors let y = Optional(2) y.map { $0 + 3
} // Optional(5)
Functors func map<U>(f: T -> U) -> U? { switch
self { case .Some(let x): return f(x) case .None: return .None } }
Functors infix operator <^> { associativity left } func <^><T,
U>(f: T -> U, a: T?) -> U? { return a.map(f) }
Functors func <^><T, U>(f: T -> U, a: T?) ->
U? { return a.map(f) } let addOne = { $0 + 1 } addOne <^> Optional(2) // Optional(3)
Applicative func apply<U>(f: (T -> U)?) -> U? { switch
f { case .Some(let someF): return self.map(someF) case .None: return .None } }
Applicatives infix operator <*> { associativity left } func <*><T,
U>(f: (T -> U)?, a: T?) -> U? { return a.apply(f) }
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 }
Applicatives add <^> Optional(2) <*> Optional(3) // Optional(5)
Applicatives add <^> Optional(2) <*> Optional(3) // Optional(5)
Applicatives add <^> Optional(2) <*> Optional(3) // Optional(5) let a
= add <^> Optional(2)
Applicatives add <^> Optional(2) <*> Optional(3) // Optional(5) let a
= add <^> Optional(2)
Applicatives add <^> Optional(2) <*> Optional(3) // Optional(5) let a
= add <^> Optional(2) let a: (b: Int) -> Int?
Monads typealias T = Double let f: T -> T
= { $0 * 2.0 } let g: (T, T) -> T = { $0 / $1 }
Monads typealias T = Double let f: T -> T
= { $0 * 2.0 } let g: (T, T) -> T = { $0 / $1 } f(g(4, 2))
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?
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) }
Monads >>- == http://adit.io/posts/2013-04-17-functors,_applicatives,_and_monads_in_pictures.html
Monads func flatten<U>(a: U??) -> U? { switch a {
case .Some(let someA): return someA case .None: return .None } }
Monads func flatMap<U>(f: T -> U?) -> U? { return
flatten(map(f)) }
Monads func flatMap<U>(f: T -> U?) -> U? { return
flatten(map(f)) } func map<U>(f: T -> U) -> U?
Monads func flatMap<U>(f: T -> U?) -> U? { return
flatten(map(f)) } func map<U>(f: T -> U) -> U?
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??
Monads infix operator >>- { associativity left } func >>-<T,
U>(a: T?, f: T -> U?) -> U? { return a.flatMap(f) }
Monads func half(a: Int) -> Int? { return a %
2 == 0 ? a / 2 : .None }
Monads func half(a: Int) -> Int? { return a %
2 == 0 ? a / 2 : .None } Optional(8) >>- half >>- half // Optional(2)
Monad Laws • Left Identity • Right Identity • Associativity
Left Identity Law let f = { Optional($0 + 1)
} let a = 1 let x = Optional(a) >>- f let y = f(a) x == y
Right Identity Law func create<T>(value: T) -> T? { return
Optional(value) } let x = Optional(1) >>- create let y = Optional(1) x == y
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
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>
Pipes & Railways @ScottWlaschin
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
Pipes let transformedX = x |> addTwo |> prodThree |>
increment |> square |> pow VS (pow(square(increment(prodThree(addTwo(x))))))
Railways http://fsharpforfunandprofit.com/posts/recipe-part2/
Argo JSON Parser + Argo Runes
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" } }
Argo Example let entities: [Model]? entities = data?.json() >>- {
$0["entities"] } >>- decode
Where Next?
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
Thanks!
Comments / Questions? @aleks_voronov a-voronov