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
Finding Happiness in Functional Programming
Search
Brandon Williams
October 01, 2016
Programming
0
610
Finding Happiness in Functional Programming
Video:
https://www.youtube.com/watch?v=A0VaIKK2ijM
Brandon Williams
October 01, 2016
Tweet
Share
More Decks by Brandon Williams
See All by Brandon Williams
Server-Side Swift from Scratch
mbrandonw
4
1.8k
Playground Driven Development
mbrandonw
0
330
Anything You Can Do I Can Do Better
mbrandonw
1
120
The Two Sides of Testing
mbrandonw
1
150
Other Decks in Programming
See All in Programming
最新のDirectX12で使えるレイトレ周りの機能追加について
projectasura
0
250
Dive into Triton Internals
appleparan
0
490
flutter_kaigi_2025.pdf
kyoheig3
1
330
Web エンジニアが JavaScript で AI Agent を作る / JSConf JP 2025 sponsor session
izumin5210
4
1.8k
PyCon mini 東海 2025「個人ではじめるマルチAIエージェント入門 〜LangChain × LangGraphでアイデアを形にするステップ〜」
komofr
3
1k
CSC509 Lecture 13
javiergs
PRO
0
250
しっかり学ぶ java.lang.*
nagise
1
380
SUZURIの規約違反チェックにおけるクリエイタフィードバックの試⾏錯誤/Trial and Error in Creator Feedback for SUZURI's Terms of Service Violation Checks
ae14watanabe
1
150
モデル駆動設計をやってみよう Modeling Forum2025ワークショップ/Let’s Try Model-Driven Design
haru860
0
160
複数チーム並行開発下でのコード移行アプローチ ~手動 Codemod から「生成AI 活用」への進化
andpad
0
170
詳細の決定を遅らせつつ実装を早くする
shimabox
1
1.2k
Building AI with AI
inesmontani
PRO
0
200
Featured
See All Featured
A Tale of Four Properties
chriscoyier
162
23k
Docker and Python
trallard
46
3.7k
What's in a price? How to price your products and services
michaelherold
246
12k
ピンチをチャンスに:未来をつくるプロダクトロードマップ #pmconf2020
aki_iinuma
127
54k
Practical Orchestrator
shlominoach
190
11k
Design and Strategy: How to Deal with People Who Don’t "Get" Design
morganepeng
132
19k
Why You Should Never Use an ORM
jnunemaker
PRO
60
9.6k
No one is an island. Learnings from fostering a developers community.
thoeni
21
3.5k
Distributed Sagas: A Protocol for Coordinating Microservices
caitiem20
333
22k
ReactJS: Keep Simple. Everything can be a component!
pedronauck
666
130k
Large-scale JavaScript Application Architecture
addyosmani
514
110k
Building an army of robots
kneath
306
46k
Transcript
Finding Happiness in Functional Programming
None
Principles that we benefited from
Separation of effects from purity
Isolation of side-effects An expression is said to have a
side-effect if its execution makes an observable change to the outside world.
Isolation of side-effects self.titleLabel.text = user.name
Isolation of side-effects func update(text: String, forLabel: UILabel) { label.text
= text } update(text: user.name, forLabel: self.titleLabel)
Isolation of side-effects self.loginButton.enabled = !self.userTextField.text.isEmpty && !self.passwordTextField.text.isEmpty
Isolation of side-effects func updateLoginButtonEnabled() { self.loginButton.enabled = !self.userTextField.text.isEmpty &&
!self.passwordTextField.text.isEmpty } func emailChanged() { self.updateLoginButtonEnabled() } func passwordChanged() { self.updateLoginButtonEnabled() }
Isolation of side-effects // Pure, functional world let emailChanged: Signal<String,
NoError> let passwordChanged: Signal<String, NoError> let loginButtonEnabled = combineLatest(emailChanged, passwordChanged) .map { !$0.isEmpty && !$1.isEmpty } // Side-effect world loginButtonEnabled.observeNext { [weak self] in self?.loginButtonEnabled.enabled = $0 }
Isolation of side-effects // Pure, functional world let emailChanged: Signal<String,
NoError> let passwordChanged: Signal<String, NoError> let loginButtonEnabled = combineLatest(emailChanged, passwordChanged) .map { !$0.isEmpty && !$1.isEmpty } // Side-effect world self.loginButton.rac.enabled = loginButtonEnabled
Surfacing of co-effects
Surfacing of co-effects ????????????????
Surfacing of co-effects If an effect is a change to
the outside world after executing an expression...
Surfacing of co-effects If an effect is a change to
the outside world after executing an expression... ...then...
Surfacing of co-effects If an effect is a change to
the outside world after executing an expression... ...then... ...a co-effect is the state of the world that the expression needs in order to execute.
Surfacing of co-effects e.g. Dependency Injection
Surfacing of co-effects Dependency Injection func currentUserIsCreator(ofProject project: Project) ->
Bool { return User.currentUser.id == project.creator.id } currentUserIsCreator(ofProject: project) // => true or false
Surfacing of co-effects Dependency Injection func user(_ user: User, isCreatorOfProject:
Project) -> Bool { return user.id == project.creator.id } user(User.currentUser, isCreatorOfProject: project) // => true or false
Surfacing of co-effects References — Colin Barrett — Functional Swift
Conference 2015 — Structure and Interpretation of Swift Programs — The work of Tomas Petricek — Coeffects: A calculus of context-dependent computation — Coeffects: The next big programming challenge
Effect/Co-effect Duality
Code to the interface you wish you had, not the
interface you were given. - Stephen Celis
An interface we were given
An interface we were given Storyboards — Very thick abstraction
layer — Separates code from data — Constantly catching up to what UIKit can do
An interface we wish we had Lenses
An interface we wish we had Lenses struct Project {
let creator: User let id: Int let name: String }
An interface we wish we had Lenses Project.lens.name // =>
Lens<Project, String>
An interface we wish we had Lenses Project.lens.name // =>
Lens<Project, String> Project.lens.name .~ "Advanced Swift" // => Project -> Project
An interface we wish we had Lenses Project.lens.name // =>
Lens<Project, String> Project.lens.name .~ "Advanced Swift" // => Project -> Project project |> Project.lens.name .~ "Advanced Swift"
An interface we wish we had Lenses project |> Project.lens.name
.~ "Advanced Swift" |> Project.lens.creator.name .~ "Chris Eidhof"
An interface we wish we had UIKit Lenses
An interface we wish we had UIKit Lenses UIView.lens.backgroundColor //
=> Lens<UIView, UIColor>
An interface we wish we had UIKit Lenses UIView.lens.backgroundColor //
=> Lens<UIView, UIColor> UIView.lens.backgroundColor .~ .redColor() // => UIView -> UIView
An interface we wish we had UIKit Lenses UIView.lens.backgroundColor //
=> Lens<UIView, UIColor> UIView.lens.backgroundColor .~ .redColor() // => UIView -> UIView view |> UIView.lens.backgroundColor .~ .redColor() |> UIView.lens.layer.cornerRadius .~ 4 |> UIView.lens.layer.masksToBounds .~ true
An interface we wish we had UIKit Lenses func roundedStyle(cornerRadius:
CGFloat) -> (UIView) -> UIView { return UIView.lens.layer.cornerRadius .~ 4 <> UIView.lens.layer.masksToBounds .~ true } view |> roundedStyle(cornerRadius: 4) |> UIView.lens.backgroundColor .~ .redColor()
An interface we wish we had UIKit Lenses let baseButtonStyle
= roundedStyle(cornerRadius: 4) <> UIButton.lens.titleLabel.font .~ UIFont(size: 16) <> UIButton.lens.contentEdgeInsets .~ .init(topBottom: 6, leftRight: 12) let greenButtonStyle = baseButtonStyle <> UIButton.lens.backgroundColor(forState: .Normal) .~ .greenColor()
An interface we wish we had UIKit Lenses let bigButtonStyle
= baseButtonStyle <> UIButton.lens.contentEdgeInsets %~ { .init(top: $0.top * 2, left: $0.left * 2, bottom: $0.bottom * 2, right: $0.right * 2) }
An interface we wish we had UIKit Lenses let baseButtonStyle
= roundedStyle(cornerRadius: 4) <> UIButton.lens.titleLabel.font %~~ { _, button in button.traitCollection.verticalSizeClass == .Compact ? UIFont(size: 12) : UIFont(size: 14) } <> UIButton.lens.contentEdgeInsets .~ .init(topBottom: 6, leftRight: 12)
Principles that we did not benefit so much from: —
D.R.Y. — S.R.P. — S.O.L.I.D. — Objects
The Result
Testing
Test-Driven Development
Test-Driven Bug Fixing
Playground-Driven Development
Screenshot testing
Event Tracking
Event Tracking
Accessibility
Love for UIKit
Be!er working relationship with Product Managers, Designers and Engineers
Finding Happiness in Functional Programming
Finding Happiness in Functional Programming
[email protected]