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
Fluent Conf 2017: Tame the frontend with Elm
Search
Jeremy Fairbank
June 21, 2017
Programming
0
160
Fluent Conf 2017: Tame the frontend with Elm
Jeremy Fairbank
June 21, 2017
Tweet
Share
More Decks by Jeremy Fairbank
See All by Jeremy Fairbank
Connect.Tech 2020: Advanced Cypress Testing
jfairbank
1
220
CodeMash 2020: Solving the Boolean Identity Crisis
jfairbank
1
160
CodeMash 2020: Practical Functional Programming
jfairbank
1
330
Connect.Tech 2019: Practical Functional Programming
jfairbank
0
370
Connect.Tech 2019: Solving the Boolean Identity Crisis
jfairbank
0
190
Lambda Squared 2019: Solving the Boolean Identity Crisis
jfairbank
0
140
All Things Open 2018: Practical Functional Programming
jfairbank
2
270
Connect.Tech 2018: Effective React Testing
jfairbank
1
180
Fluent Conf 2018: Building web apps with Elm Tutorial
jfairbank
2
870
Other Decks in Programming
See All in Programming
ボトムアップの生成AI活用を推進する社内AIエージェント開発
aku11i
0
1.6k
AIエージェントでのJava開発がはかどるMCPをAIを使って開発してみた / java mcp for jjug
kishida
4
430
Java_プロセスのメモリ監視の落とし穴_NMT_で見抜けない_glibc_キャッシュ問題_.pdf
ntt_dsol_java
0
140
ネストしたdata classの面倒な更新にさようなら!Lensを作って理解するArrowのOpticsの世界
shiita0903
1
320
チーム開発の “地ならし"
konifar
6
3.7k
SUZURIの規約違反チェックにおけるクリエイタフィードバックの試⾏錯誤/Trial and Error in Creator Feedback for SUZURI's Terms of Service Violation Checks
ae14watanabe
1
140
KoogではじめるAIエージェント開発
hiroaki404
1
450
ノーコードからの脱出 -地獄のデスロード- / Escape from Base44
keisuke69
0
680
Verilator + Rust + gRPC と Efinix の RISC-V でAIアクセラレータをAIで作ってる話 RTLを語る会(18) 2025/11/08
ryuz88
0
350
Eloquentを使ってどこまでコードの治安を保てるのか?を新人が考察してみた
itokoh0405
0
3.1k
例外処理を理解して、設計段階からエラーを見つけやすく、起こりにくく #phpconfuk
kajitack
12
5.8k
SidekiqでAIに商品説明を生成させてみた
akinko_0915
0
130
Featured
See All Featured
Put a Button on it: Removing Barriers to Going Fast.
kastner
60
4.1k
A designer walks into a library…
pauljervisheath
210
24k
For a Future-Friendly Web
brad_frost
180
10k
Building Applications with DynamoDB
mza
96
6.7k
How to Ace a Technical Interview
jacobian
280
24k
RailsConf & Balkan Ruby 2019: The Past, Present, and Future of Rails at GitHub
eileencodes
140
34k
A better future with KSS
kneath
239
18k
[RailsConf 2023 Opening Keynote] The Magic of Rails
eileencodes
31
9.7k
Embracing the Ebb and Flow
colly
88
4.9k
StorybookのUI Testing Handbookを読んだ
zakiyama
31
6.3k
Visualizing Your Data: Incorporating Mongo into Loggly Infrastructure
mongodb
48
9.8k
Stop Working from a Prison Cell
hatefulcrawdad
272
21k
Transcript
Tame the frontend with Elm Jeremy Fairbank / @elpapapollo
Software is broken. We are here to fix it. Say
[email protected]
Happiness
None
✓ Easier to write code ✓ Easier to write tests
✓ Easier to refactor
elm
No runtime exceptions in practice.
No undefined is not a function
Fast
One framework. No fatigue. Update View Model Messages
elm
Functional
greet name = "Hello, " ++ name greet "Fluent Conf"
-- Hello, Fluent Conf
greet name = "Hello, " ++ name greet "Fluent Conf"
-- Hello, Fluent Conf
greet name = "Hello, " ++ name greet "Fluent Conf"
-- Hello, Fluent Conf
greet name = "Hello, " ++ name greet "Fluent Conf"
-- Hello, Fluent Conf Single Expression
greet name = "Hello, " ++ name greet "Fluent Conf"
-- Hello, Fluent Conf
greet name = "Hello, " ++ name greet "Fluent Conf"
-- Hello, Fluent Conf
Pure Data in Data out
Pure No side effects
Pure Predictable and Testable!
add x y = x + y add 2 3
== 5 add 2 3 == 5 add 2 3 == 5
add x y = x + y add 2 3
== 5 add 2 3 == 5 add 2 3 == 5
add x y = x + y add 2 3
== 5 add 2 3 == 5 add 2 3 == 5
Expressive Terse and declarative code
myList = [1, 2, 3, 4, 5] double n =
n * 2 doubleNumbers list = List.map double list doubleNumbers myList -- [2, 4, 6, 8, 10]
myList = [1, 2, 3, 4, 5] double n =
n * 2 doubleNumbers list = List.map double list doubleNumbers myList -- [2, 4, 6, 8, 10]
myList = [1, 2, 3, 4, 5] double n =
n * 2 doubleNumbers list = List.map double list doubleNumbers myList -- [2, 4, 6, 8, 10]
myList = [1, 2, 3, 4, 5] double n =
n * 2 doubleNumbers list = List.map double list doubleNumbers myList -- [2, 4, 6, 8, 10]
myList = [1, 2, 3, 4, 5] double n =
n * 2 doubleNumbers list = List.map double list doubleNumbers myList -- [2, 4, 6, 8, 10]
myList = [1, 2, 3, 4, 5] double n =
n * 2 doubleNumbers list = List.map double list doubleNumbers myList -- [2, 4, 6, 8, 10]
Curried Functions Building blocks
add x y = x + y add 1 2
-- 3 (add 1) 2 -- 3
add x y = x + y add 1 2
-- 3 (add 1) 2 -- 3
add x y = x + y add 1 2
-- 3 (add 1) 2 -- 3
add x y = x + y add 1 2
-- 3 (add 1) 2 -- 3 New function created
increment = add 1 increment 2 -- 3 increment 41
-- 42
increment = add 1 increment 2 -- 3 increment 41
-- 42
increment = add 1 increment 2 -- 3 increment 41
-- 42
Pipes Expressive Chaining
exclaim (greet (String.toUpper "Tucker")) greet name = "Hello, " ++
name exclaim phrase = phrase ++ "!"
"Tucker" |> String.toUpper |> greet |> exclaim
"Tucker" |> String.toUpper |> greet |> exclaim
|> String.toUpper "Tucker" |> greet |> exclaim
"TUCKER" |> greet |> exclaim
|> greet "TUCKER" |> exclaim
"Hello, TUCKER" |> exclaim
|> exclaim "Hello, TUCKER"
"Hello, TUCKER!"
No Runtime Exceptions
Strong Static Types life : Int life = 42 greeting
: String greeting = "Hello World" isTrue : Bool isTrue = True numbers : List Int numbers = [1, 2, 3]
Strong Static Types life : Int life = 42 greeting
: String greeting = "Hello World" isTrue : Bool isTrue = True numbers : List Int numbers = [1, 2, 3]
Strong Static Types life : Int life = 42 greeting
: String greeting = "Hello World" isTrue : Bool isTrue = True numbers : List Int numbers = [1, 2, 3]
greet : String -> String greet name = "Hello, "
++ name add : Int -> Int -> Int add x y = x + y
greet : String -> String greet name = "Hello, "
++ name add : Int -> Int -> Int add x y = x + y
greet : String -> String greet name = "Hello, "
++ name add : Int -> Int -> Int add x y = x + y
greet : String -> String greet name = "Hello, "
++ name add : Int -> (Int -> Int) add x y = x + y
The argument to function `greet` is causing a mismatch. 11|
greet 42 ^^ Function `greet` is expecting the argument to be: String But it is: number Compile time static type checks
Immutable Data Safe and Consistent
dog : { name : String, age : Int }
dog = { name = "Tucker" , age = 11 } dog.name -- "Tucker" dog.age -- 11 Records
dog : { name : String, age : Int }
dog = { name = "Tucker" , age = 11 } dog.name -- "Tucker" dog.age -- 11 Records
dog : { name : String, age : Int }
dog = { name = "Tucker" , age = 11 } dog.name -- "Tucker" dog.age -- 11 Records
dog : { name : String, age : Int }
dog = { name = "Tucker" , age = 11 } dog.name -- "Tucker" dog.age -- 11 Records
haveBirthday dog = { dog | age = dog.age +
1 } dog = { name = "Tucker", age = 11 } olderDog = haveBirthday dog olderDog.age -- 12 olderDog.name -- "Tucker" dog.age -- 11 dog.name -- "Tucker" Create New Data
haveBirthday dog = { dog | age = dog.age +
1 } dog = { name = "Tucker", age = 11 } olderDog = haveBirthday dog olderDog.age -- 12 olderDog.name -- "Tucker" dog.age -- 11 dog.name -- "Tucker" Create New Data
haveBirthday dog = { dog | age = dog.age +
1 } dog = { name = "Tucker", age = 11 } olderDog = haveBirthday dog olderDog.age -- 12 olderDog.name -- "Tucker" dog.age -- 11 dog.name -- "Tucker" Create New Data
haveBirthday dog = { dog | age = dog.age +
1 } dog = { name = "Tucker", age = 11 } olderDog = haveBirthday dog olderDog.age -- 12 olderDog.name -- "Tucker" dog.age -- 11 dog.name -- "Tucker" Create New Data
haveBirthday dog = { dog | age = dog.age +
1 } dog = { name = "Tucker", age = 11 } olderDog = haveBirthday dog olderDog.age -- 12 olderDog.name -- "Tucker" dog.age -- 11 dog.name -- "Tucker" Create New Data
haveBirthday dog = { dog | age = dog.age +
1 } dog = { name = "Tucker", age = 11 } olderDog = haveBirthday dog olderDog.age -- 12 olderDog.name -- "Tucker" dog.age -- 11 dog.name -- "Tucker" Create New Data
Custom Types Domain-specific code
type alias Dog = { name : String , age
: Int , breed : Breed } type Breed = Sheltie | Poodle
type alias Dog = { name : String , age
: Int , breed : Breed } type Breed = Sheltie | Poodle
type alias Dog = { name : String , age
: Int , breed : Breed } type Breed = Sheltie | Poodle Union Type
dog : Dog dog = { name = "Tucker" ,
age = 11 , breed = Sheltie }
dog : Dog dog = { name = "Tucker" ,
age = 11 , breed = Sheltie }
dog : Dog dog = { name = "Tucker" ,
age = 11 , breed = Sheltie }
No null or undefined
type Maybe a = Just a | Nothing
type Maybe a = Just a | Nothing Wraps the
successful value
type Maybe a = Just a | Nothing Represents no
result or missing value
type Maybe a = Just a | Nothing Type Variable
type Maybe a = Just a | Nothing Either I
have Just the value a, or I have Nothing.
divide : Float -> Float -> Maybe Float divide x
y = if y == 0 then Nothing else Just (x / y) divide 4 2 -- Just 2 divide 4 0 -- Nothing
divide : Float -> Float -> Maybe Float divide x
y = if y == 0 then Nothing else Just (x / y) divide 4 2 -- Just 2 divide 4 0 -- Nothing
divide : Float -> Float -> Maybe Float divide x
y = if y == 0 then Nothing else Just (x / y) divide 4 2 -- Just 2 divide 4 0 -- Nothing
divide : Float -> Float -> Maybe Float divide x
y = if y == 0 then Nothing else Just (x / y) divide 4 2 -- Just 2 divide 4 0 -- Nothing
divide : Float -> Float -> Maybe Float divide x
y = if y == 0 then Nothing else Just (x / y) divide 4 2 -- Just 2 divide 4 0 -- Nothing
divide : Float -> Float -> Maybe Float divide x
y = if y == 0 then Nothing else Just (x / y) divide 4 2 -- Just 2 divide 4 0 -- Nothing
case divide 4 2 of Just n -> "Result is
" ++ (toString n) Nothing -> "No Result"
case divide 4 2 of Just n -> "Result is
" ++ (toString n) Nothing -> "No Result"
case divide 4 2 of Just n -> "Result is
" ++ (toString n) Nothing -> "No Result"
case divide 4 2 of Just n -> "Result is
" ++ (toString n) Nothing -> "No Result"
case divide 4 2 of Just n -> "Result is
" ++ (toString n) -- Nothing -> -- "No Result"
Exhaustive matching This `case` does not have branches for all
possibilities. 21|> case divide 4 2 of 22|> Just n -> 23|> "Result is " ++ (toString n) You need to account for the following values: Maybe.Nothing Add a branch to cover this pattern!
Update View Model Messages The Elm Architecture
Demos The Elm Architecture in Action
Getting Started • elm-lang.org • elm-lang.org/examples • guide.elm-lang.org • www.elm-tutorial.org
• builtwithelm.co • Slack • elmlang.herokuapp.com
Say
[email protected]
Thank you! Jeremy Fairbank / @elpapapollo