Introduction to Elm
James Morcom (@morcs, morcs.com)
What is Elm?
- Programming Language (created by Evan Czaplicki)
- Browser apps
- Pure functional language
- Syntax like Haskell, F# (ML family)
- Compiles to JavaScript
- Front-end framework (like React/Angular/Vue)
- Single state/event dispatch model (Redux)
- REPL, package manager, hot-reloading etc.
Why Elm?
Imagine a world...
- No null/undefined
- No language cruft
- No exceptions
- Illegal states unrepresentable
- Compiler finds the errors...
Just functions and data!
Also...
- Learn FP
- It's fast!!

https://bit.ly/2HqPNqX

"Pure" functions?
- All functions in Elm are "pure" and "total"
- Can be represented by a lookup table
| Input (Int) | Output (Int) |
|---|---|
| -1 | 1 |
| 0 | 0 |
| 1 | 1 |
| 2 | 4 |
| 3 | 9 |
| ... | ... |
- Every possible input appears once
- Every input has an output
- Output always the same
"Pure" functions?
| Input (Int) | Output (Int) |
|---|---|
| -1 | 1 |
| 0 | 0 |
| 1 | 1 |
| ... | ... |
- Can't read from globals, fields (this), DBs, console (no hidden inputs, deterministic)
- Can't write to globals, DBs, send HTTP either!
(no hidden outputs, no side-effects)
- Easy testing (no mocking required)
- Easy to optimize/parallellise

Syntax - Functions & values
circumference r =
2 * pi * radd x y = x + ypi = 3.142result = add 3 5
-- result == 7Syntax - Lists
results =
[ circumference 2
, add 3 4
, 12
]numbers = [1, 2, 3, 4, 5]Syntax - Markup
- Angular uses separate HTML templates
- React uses JSX - one file, two languages
- In Elm, markup is just code
Elm is different
Exercise 0
Warmup
https://morcs.com/introduction-to-elm/
Ctrl-click "View Exercise"
Try compiling - should get an error
Warmup
Elm code
HTML output
main = table [] []
-- hit compile, compiler validates HTML!
<table></table>
main = table [ class "table" ] []
-- again, hit compile to validate HTML
<table class="table"></table>
main =
table [ class "table" ] [
tr [] []
]
-- try the FORMAT button!
<table class="table">
<tr></tr>
</table>
main =
table [ class "table" ]
[ tr []
[ th [] []
]
-- hit compile, valid HTML!
]
<table class="table">
<tr> <th></th> </tr>
</table>
main =
table [ class "table" ]
[ tr []
[ th [ scope "row" ] [ text "Elm" ] ]
]
-- should start to see output
<table class="table">
<tr> <th scope="row">Elm</th> </tr>
</table>
main =
table [ class "table" ]
[ tr []
[ th [ scope "row" ] [ text "Elm" ]
, td [] [ text "10" ]
]
]
<table class="table">
<tr> <th scope="row">Elm</th> <td>10</td> </tr>
</table>
main =
table [ class "table" ]
[ renderRow
]
renderRow =
tr []
[ th [ scope "row" ] [ text "Elm" ]
, td [] [ text "10" ]
]
<table class="table">
<tr> <th scope="row">Elm</th> <td>10</td> </tr>
</table>
main =
table [ class "table" ]
[ renderRow "Elm"
, renderRow "React"
]
renderRow : String -> Html msg -- type annotation
renderRow name =
tr []
[ th [ scope "row" ] [ text name ]
, td [] [ text "10" ]
]
<table class="table">
<tr> <th scope="row">Elm</th> <td>10</td> </tr>
<tr> <th scope="row">React</th> <td>10</td> </tr>
</table>
main =
table [ class "table" ]
[ renderRow "Elm" 10 -- web component!
, renderRow "React" 9
]
renderRow : String -> Int -> Html msg
renderRow name score =
tr []
[ th [ scope "row" ] [ text name ]
, td [] [ text (toString score) ]
]
<table class="table">
<tr> <th scope="row">Elm</th> <td>10</td> </tr>
<tr> <th scope="row">React</th> <td>9</td> </tr>
</table>
Exercise 1
Markup
https://morcs.com/introduction-to-elm/
Instructions/markup are on this page!
Types
james : { name : String, age : Int }
james =
{ name = "James"
, age = 12
}james : (String, Int)
james = ("James", 12)Records
Tuples
Dealing with states
Use record type?
model :
{ cards : List Card
, loaded : Bool
, errorMessage : String
, hasError : Bool
}model =
{ cards = []
, loaded = True
, errorMessage = "Cards didn't load"
, hasError = True
}Union types
type Model
= Loading
| Success (List Card)
| Error String
case model of
Loading ->
-- show a loading spinner
Success cards ->
-- render all the cards
Error msg ->
-- show msg with red stylingmodel = Error "Badness happened"
type Bool
= True
| False
type List a
= NonEmptyList a (List a)
| Empty
- Presence/absence of value (no need for null)
- Success/failure state
(no need for exceptions)
Exercise 2
Union types
https://morcs.com/introduction-to-elm/
Interactivity
The essense of every Elm program:
- Model — a nice representation of your application state.
- View — a function that turns models into HTML.
- Update — given a user-input messages and the model, produce a new model.

The back-end isn't ready yet
...but the client wants to see what it'll look like in various states
Lets add some buttons so they can switch between states.
model : model
view : model -> Html msg
update : msg -> model -> modeltype Model
= Loading
| Success (List Card)
| Error Stringtype Msg
= TestSuccess
| TestError StringButtons
Exercise 3
The update function
https://morcs.com/introduction-to-elm/
type Maybe a
= Nothing
| Just aNo nulls!
Only Maybes
var empty = new List<Card>();var card = empty.FirstOrDefault();var card = empty.First();var name = card.NameException!!!
Exception!!!
List.head : List a -> Maybe aC#
Elm
card = List.head []
name = card.nameWon't compile!!!
name = case List.head [] of
Nothing ->
"Anonymous"
Just card ->
card.name| Input (List Int) | Output (Int) ? |
|---|---|
| [] | BOOM! / null |
| [1] | 1 |
| [1,2] | 1 |
| [2] | 2 |
| ... | ... |
C#/Linq
First / FirstOrDefault
| Input (List Int) | Output (Maybe Int) |
|---|---|
| [] | Nothing |
| [1] | Just 1 |
| [1,2] | Just 1 |
| [2] | Just 2 |
| ... | ... |
Elm
List.head
Exercise 4
The Maybe type
https://morcs.com/introduction-to-elm/
type Result error value
= Ok value
| Err errorNo exceptions!
Only Results
Extending messages
init : (model, Cmd msg)
update : msg -> model -> (model, Cmd msg)
view : model -> Html msg
subscriptions : model -> Sub msgExercise 5
Calling an API
https://morcs.com/introduction-to-elm/
More Exercises
https://morcs.com/introduction-to-elm/
How can Elm do stuff?
- Describe events/effects as data that can be inputs/outputs of pure functions
- Inputs come from framework
- Outputs describe effects for framework to carry out
...if we only have pure functions
| Input | Output |
|---|---|
| Card X was clicked | Model with Card X selected |
| Load more was clicked | Go fetch URL (with callback) |
Syntax - More Lists
result =
List.map circumference <| List.filter isEven numbersresult =
List.map circumference numbersresult =
numbers
|> List.filter isEven
|> List.map circumferenceresult =
List.map circumference (List.filter isEven numbers)Syntax - Maybe vs List
type Maybe a
= Nothing
| Just atype List a
= Empty
| NonEmptyList a (List a)
Syntax - Maybe vs List
cardName : Maybe Card -> String
cardName selected =
selected
|> Maybe.map .name
|> Maybe.withDefault "-- not selected --"
selected = Just { name = "Brian" }
result = cardName selected
-- result == "Brian"
selected = Nothing
result = cardName selected
-- result == "-- not selected --" Multiple Parameters
add x y = x + yaddThree = add 3
result = addThree 4circumference = \r -> 2 * pi * radd = \x -> (\y -> x + y)
addThree = add 3 -- \y -> 3 + yLambda syntax
add : number -> number -> number
addThree : number -> number
result : number
Multiple Parameters

Introduction to Elm
By James Morcom
Introduction to Elm
- 1,415