James Morcom (@morcs, morcs.com)
Imagine a world...
Just functions and data!
Also...
https://bit.ly/2HqPNqX
| Input (Int) | Output (Int) |
|---|---|
| -1 | 1 |
| 0 | 0 |
| 1 | 1 |
| 2 | 4 |
| 3 | 9 |
| ... | ... |
| Input (Int) | Output (Int) |
|---|---|
| -1 | 1 |
| 0 | 0 |
| 1 | 1 |
| ... | ... |
circumference r =
2 * pi * radd x y = x + ypi = 3.142result = add 3 5
-- result == 7
results =
[ circumference 2
, add 3 4
, 12
]numbers = [1, 2, 3, 4, 5]https://morcs.com/introduction-to-elm/
Ctrl-click "View Exercise"
Try compiling - should get an error
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>
https://morcs.com/introduction-to-elm/
Instructions/markup are on this page!
james : { name : String, age : Int }
james =
{ name = "James"
, age = 12
}james : (String, Int)
james = ("James", 12)Records
Tuples
model :
{ cards : List Card
, loaded : Bool
, errorMessage : String
, hasError : Bool
}model =
{ cards = []
, loaded = True
, errorMessage = "Cards didn't load"
, hasError = True
}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
https://morcs.com/introduction-to-elm/
The essense of every Elm program:
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
https://morcs.com/introduction-to-elm/
type Maybe a
= Nothing
| Just aOnly 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 |
| ... | ... |
First / FirstOrDefault
| Input (List Int) | Output (Maybe Int) |
|---|---|
| [] | Nothing |
| [1] | Just 1 |
| [1,2] | Just 1 |
| [2] | Just 2 |
| ... | ... |
List.head
https://morcs.com/introduction-to-elm/
type Result error value
= Ok value
| Err errorOnly Results
init : (model, Cmd msg)
update : msg -> model -> (model, Cmd msg)
view : model -> Html msg
subscriptions : model -> Sub msghttps://morcs.com/introduction-to-elm/
https://morcs.com/introduction-to-elm/
...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) |
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)
type Maybe a
= Nothing
| Just atype List a
= Empty
| NonEmptyList a (List a)
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 --" 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