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
Sponsored
·
SiteGround - Reliable hosting with speed, security, and support you can count on.
→
Oleksandr Voronov
September 15, 2015
Programming
1.2k
2
Share
Alexander Voronov
Swift: Going Functional
https://youtu.be/Dc9aKhs37BE
Oleksandr Voronov
September 15, 2015
More Decks by Oleksandr Voronov
See All by Oleksandr Voronov
Controllable Randomness in Unit Tests
alexandervoronov
1
71
Modularizing your iOS apps
alexandervoronov
0
180
TDD in Real World
alexandervoronov
1
270
Building CLI with Swift
alexandervoronov
1
340
Stanfy MadCode 10: From Java to Kotlin, from Objective-C to Swift
alexandervoronov
0
250
ReactiveCocoa
alexandervoronov
0
190
Other Decks in Programming
See All in Programming
作って学ぶ、 JSX (TSX) ランタイムの基本
syumai
7
1.5k
気づいたらRubyで100作品 ー クリエイティブコーディングが生活の一部になるまで / 100 Ruby Sketches Later: How Creative Coding Became Part of My Life
chobishiba
3
530
エージェンティックRAGにAWSで入門しよう!
har1101
5
110
Composerを使ったサプライチェーン攻撃の様子を眺めてみる #phpstudy
o0h
PRO
2
220
Copilot CLI の継戦能力を高める コンテキスト管理
nozomutu
1
1.2k
TypeSpec で繋ぐ複数プロダクトの型安全
maroon8021
1
360
代数的データ型って何が嬉しいの? #frontend_phpcon_do
kajitack
8
3.1k
Claspは野良GASの夢をみるか
takter00
0
160
TSKaigi 2026 TypeScriptバックエンドのオブザーバビリティ戦略 — Datadog × NestJSの実践
taiseiyamamotoan
2
270
tsserverとは何だったのか、これからどうなるのか
nowaki28
1
440
不変条件と整合性境界—ビジネスが決める設計判断と実現パターン / Invariants and Consistency Boundaries
nrslib
13
3.4k
軽量Java基盤の設計 DIコンテナに頼らない、長期保守と1秒起動の実現 JJUG CCC 2026 Spring
macha64
0
430
Featured
See All Featured
Build your cross-platform service in a week with App Engine
jlugia
234
18k
Evolving SEO for Evolving Search Engines
ryanjones
0
210
Information Architects: The Missing Link in Design Systems
soysaucechin
0
960
Easily Structure & Communicate Ideas using Wireframe
afnizarnur
194
17k
Beyond borders and beyond the search box: How to win the global "messy middle" with AI-driven SEO
davidcarrasco
3
150
Joys of Absence: A Defence of Solitary Play
codingconduct
1
380
How to Grow Your eCommerce with AI & Automation
katarinadahlin
PRO
1
200
Refactoring Trust on Your Teams (GOTO; Chicago 2020)
rmw
35
3.5k
Designing Powerful Visuals for Engaging Learning
tmiket
1
390
Public Speaking Without Barfing On Your Shoes - THAT 2023
reverentgeek
1
410
How STYLIGHT went responsive
nonsquared
100
6.2k
jQuery: Nuts, Bolts and Bling
dougneiner
66
8.5k
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