Introduction to Elm
Tessa Kelly
twitter: @t_kelly9, github: @tesk9
NoRedInk
Helping teachers
teach grammar and writing
... using Elm
Introduction
Who's who
&
What are we doing here
About this Workshop
Pedagogical Approach
The Elevator Pitch
-
No Runtime Exceptions
-
Great Performance
- Enforced Semantic Versioning
- Small Assets
- JavaScript Interop
Getting Started
Fingers to Keyboards
ELm LIve Editor
Section 1
Strings & String Operations
Conditional Logic
Debugging
logging values, crashing, time traveling
concat strings, type coercion, functions
comparisons, if/else expressions, handling cases
building a static view with elm/html
Example 1: A Static View
https://ellie-app.com/3K8f7626MXqa1
Problem 1: that's not my name!
Change the view to use your name.
Problem 2: string concatenation
Modify your code to use string concatenation
Problem 3: make a helper
Add a helper that returns an introduction string given a name
Exercise 1: A Static View
https://ellie-app.com/3K8x8np6hbva1
Problem 1: I don't have alligators!
Say what kind of pets you do have
Problem 2: string concatenation
Modify your code to use string concatenation
Problem 3: make a helper
Add & use a helper that returns a sentence like "I have 3 pet mice", where "mice" is the argument.
Example 2: Strings & Integers
-- ELM CODE
import String
three =
String.fromInt 3
maybe3 =
String.toInt three
https://package.elm-lang.org/packages/elm/core/latest/String#int-conversions
// JAVASCRIPT CODE
let three = 3;
three.toString();
let maybeThree = parseInt(three, 10);
Example 3: Conditional Logic
-- ELM CODE
sign count =
if count < 0 then
"Negative"
else if count == 0 then
"Zero"
else
"Positive"
{- Use if/else when you are working
with buckets or intervals -}
https://package.elm-lang.org/packages/elm/core/latest/String#int-conversions
-- ELM CODE
result count =
case count of
0 ->
"Zero"
1 ->
"One"
9 ->
"Tessa's favorite number"
_ ->
"Some other number"
{- Use a case statement when you
are interested in matching against
particular values -}
notZero number =
number /= 0
Example 4: String, Int, Conditional Logic
https://ellie-app.com/3K8f7626MXqa1
Problem 1: how old am I?
Say how old you are in your introduction
Problem 2: pluralization
Handle 1-year-old case using a case expression
Problem 3: pluralization, part 2
Handle 1-year-old case with if/else expressions
Exercise 2: String, Int, Conditional Logic
https://ellie-app.com/3KjznK96brsa1
Problem 1: how many pets?
Modify your helper to accept an integer number of pets.
Problem 2: pluralization
Handle 1-pet case using a case expression
Problem 3: pluralization, part 2
Handle 1-pet case with an if/else expression
Example 5: Working with Errors
-- ELM CODE
main =
div []
[ text (buildIntro 5 "Tessa")
]
buildIntro name age =
"Hello, my name is "
++ name
++ ". "
++ (case age of
1 ->
"I am 1 year old."
_ ->
"I am " ++ String.fromInt age ++ " years old."
)
https://ellie-app.com/3KjHwGd2h7va1 (compiling)
Type Mismatch
Line 9, Column 30
The 2nd argument to `buildIntro` is not what I expect:
9| [ text (buildIntro 5 "Tessa")
^^^^^^^
This argument is a string of type:
String
But `buildIntro` needs the 2nd argument to be:
Int
Hint: I always figure out the argument types from left to right. If an argument
is acceptable, I assume it is “correct” and move on. So the problem may actually
be in one of the previous arguments!
Hint: Want to convert a String into an Int? Use the String.toInt function!
main =
div []
[ text (buildIntro 5 "Tessa")
]
buildIntro : Int -> String -> String
buildIntro name age =
"Hello, my name is "
++ name
++ ". "
++ (case age of
1 ->
"I am 1 year old."
_ ->
"I am " ++ String.fromInt age ++ " years old."
)
Type Mismatch
Line 19, Column 17
The 1st pattern in this `case` causing a mismatch:
18| ++ (case age of
19|> 1 ->
20| "I am 1 year old."
21|
22| _ ->
23| "I am " ++ String.fromInt age ++ " years old."
The first pattern is trying to match integers:
Int
But the expression between `case` and `of` is:
String
Hint: Want to convert an Int into a String? Use the String.fromInt function!
These can never match! Is the pattern the problem? Or is it the expression?
Exercise 3: Debugging Code
https://ellie-app.com/3KjVDZYwhtca1
Problem 1: fix naming errors
Problem 2: fix type error
Problem 3: is this code safe?
Consider: what would happen if we accidentally passed the plural value into the singular slot?
Example 6: Going further with Debug
-- ELM CODE
_ =
Debug.log "label the output" 100000
-- Debug.todo:
-- https://ellie-app.com/3Kk5nkQRRVsa1
-- Time traveling:
-- https://ellie-app.com/new
https://package.elm-lang.org/packages/elm/core/latest/Debug
Questions? Break?
Section 2
Opinionated Wiring
Handling User Actions
Browser.sandbox and the Elm Architecture
Html.Events.onClick
interactivity and the Elm Architecture
Example 1: Browser.sandbox
-- ELM CODE
import Browser
main =
Browser.sandbox
{ init = "Starting value"
, view = \currentValue -> text currentValue
, update =
\howToChangeTheCurrentValue currentValue ->
-- How might we want to change the current value?
-- What do you think `howToChangeTheCurrentValue` might be?
currentValue
}
{- Remember, `main` is special in Elm! -}
https://package.elm-lang.org/packages/elm/core/latest/String#int-conversions
twitter: @01k
Kolja Wilcke
https://opensource.zalando.com/elm-street-404/
Example 2: An Interactive View
https://ellie-app.com/3KkLpMnypQTa1
Problem 1: use Browser.sandbox
Set up wiring for an interactive application
Problem 2: add a working button
Increase the age
Problem 3: the fountain of youth
Consider: how might we support a second button that decreased the age?
Exercise 1: An Interactive View
https://ellie-app.com/3Km3mMN8nhfa1
Problem 1: use Browser.sandbox
Set up wiring for an interactive application
Problem 2: add a working button
Acquire a new pet with every click
Problem 3: decrement pets
Add a button for when your pets move to the country to live on a big farm where there's lots of room for them to run & play
Code Review
https://ellie-app.com/3KmdjnrNgmha1
Questions? Break?
Section 3
Modeling state
Approaches to updating state
records & type aliases
types & case expressions
building a more complex application
Example 1: Records
https://ellie-app.com/3KnjcvvJ3vCa1
Problem 1: key-value pairs
Create key value pair mappings for name and for age
Problem 2: update a value
Update the age value
Problem 3: use this record as our "model"
Replace the age integer model with a record-based model, to which we will be able to add more fields & state
Exercise 1: Records
https://ellie-app.com/3KnnF96VhcZa1
Problem 1: key-value pairs
Create key value pair mappings for pet species and count
Problem 2: update the number of pets
Update the pet value
Problem 3: use this record as our "model"
Replace the count integer model with a record-based model, to which we will be able to add more fields & state
Example 2: Using Record Values
https://ellie-app.com/3KntTjq3GFBa1
Problem 1: de-structuring records
Change the introduction helper to take the entire model. Use record deconstruction
Problem 2: add a type annotation
Add a type annotation to `buildIntro`
Problem 3: introduce a type alias
Add a type alias for the model. Experiment with how this addition changes the error messages you might run into
Exercise 2: Using Record Values
https://ellie-app.com/3KnFkxw4WZ4a1
Problem 1: de-structuring records
Change the helper to take the entire model. Use record deconstruction
Problem 2: add a type annotation
Add a type annotation to `myPetsAre`
Problem 3: introduce a type alias
Add a type alias for the model. Currently, the model has a `speciesSingular` field and a `speciesPlural` field. What alternatives are there? What might be nicer?
Example 3: Type Aliases
-- ELM CODE
-- Ways to use record type aliases:
{-| 1. Make an item of the right "shape" -}
init : Model
init =
{ name = "Tessa"
, age = 0
}
{-| 1. Pass the name of the alias the arguments in order -}
initTwo : Model
initTwo =
Model "Tessa" 0
-- ELM CODE
-- Ways to use other kinds of type aliases:
type alias Name =
String
type alias Id =
Int
type alias HasANameAndId a =
{ a | name : Name, id: Id }
Example 4: Lots of Updates
https://ellie-app.com/3KnQq5LfnFra1
Problem 1: what is `update`'s type?
Add a type annotation to the `update` function
Problem 2: change name
Allow the user to change their username
Problem 3: change name to "age"
What happens? Consider: what are our options?
Example 5: Custom Types
-- ELM CODE
type Animal
= Cat
| Dog
| Monkey
| Horse
isACat : Animal -> Bool
isACat animal =
case animal of
Cat ->
True
_ ->
False
-- ELM CODE
type CurrentUser
= LoggedIn { name : String, id : Int }
| LoggedOut
logInUser : Int -> String -> CurrentUser
logInUser id name =
LoggedIn { id = id, name = name }
logOutUser : CurrentUser
logOutUser =
LoggedOut
Example 6: Using Types
https://ellie-app.com/3Kp7xDn8YGqa1
Problem 1: describe state changes
Using a new, custom type, describe the possible state changes in the application
Problem 2: use the new `Msg`type
Use the new Msg type in the update function
Problem 3: add `view` type annotation
Add a type annotation to the `view` code. What do you notice? How do you think `Html` works?
Exercise 2: Using Types
https://ellie-app.com/3KpcxMMZ8rZa1
Problem 1: describe state changes
Using a new, custom type, describe the possible state changes in the application
Problem 2: use the new type
Use the new type in the update function
Problem 3: going further
Consider: where else in the application might you want to use a custom type?
Questions? Break?
Section 4
Strings, Ints, Flow, Debugging
Elm Architecture
Records, Type Aliases, and Types
create type aliases and custom types, work with records
strings, converting between strings & ints, case expressions, debugging..
handling user actions, application architecture, model/view/update pattern
Reviewing what we've discussed so far
twitter: @01k
Kolja Wilcke
https://opensource.zalando.com/elm-street-404/
Section 5
Installing a package
Using a package
importing a styling package and getting started using it
Use a css library for strictly typed CSS
finding and installing a package from the package website
Example 1: Package Site
https://package.elm-lang.org/
notZero number =
number /= 0
Exercise 1: Using the Docs
https://package.elm-lang.org/
Problem 1: booleans
find and read about Booleans in Elm. What do you notice about how they're modeled?
Problem 2: tuples
find and read about tuples in elm. When might you use a tuple? What does `mapFirst` do?
Problem 3: find a function
search for `map` in elm/core. Which modules include a `map` function? Why might this be?
Example 2: On the Command Line
➜ my-elm-project
elm install rtfeldman/elm-css
Here is my plan:
Add:
Skinney/murmur3 2.0.8
rtfeldman/elm-css 15.1.0
rtfeldman/elm-hex 1.0.0
Would you like me to update your elm.json accordingly? [Y/n]: y
Dependencies loaded from local cache.
Dependencies ready!
Example 3: On Ellie
https://ellie-app.com/3Lc3vWS7FVna1
Problem 1: prettify
add some style attributes to make more pretty
Problem 2: install rtfeldman/elm-css
yay libraries!
Problem 3: use elm-css for typed styles
convert the `style` tags to use elm-css instead
Exercise 2: Adding Some Style
https://ellie-app.com/3Lc8qsVGN4Ya1
Problem 1: prettify
install rtfeldman/elm-css & beautify
Problem 2: follow your heart
add animal pictures & customize your work! what other features do you want your pets page to have?
Example 4: mdgriffith/elm-ui
https://package.elm-lang.org/packages/mdgriffith/elm-ui/latest/
Section 5
Lists and List Operations
Getting values from Lists
Pipe operator
transforming a value with multiple functions
creating lists, mapping
de-structuring lists, `Maybe`s
composing with lists
Example 1: Many Bats
https://ellie-app.com/3LcSHg4RtP7a1
Problem 1: show a bat
show the species & picture of the first bat.
Problem 2: show all the bats
reuse a helper to show each bat
Problem 3: sort the bats
order the bats on the page by size
Exercise 1: List Operations
https://ellie-app.com/3LhYsYnhyC8a1
Problem 1: fix the tests
all the unit tests are failing! Please make them pass by implementing the functions.
some of these problems will require that you look up new functions in the documentation. have fun!
some of these may be challenging. if you feel stuck on one, move on to the next one.
Code Review
https://ellie-app.com/3LhYvf29vpDa1
Example 2: Piping
-- ELM CODE
{-| Keeps words that are longer than 10 characters
-}
keepLongWords : List String -> List String
keepLongWords inputList =
List.filter (\item -> String.length item > 5) (List.concatMap String.words inputList)
{-| Version 2
-}
keepLongWords : List String -> List String
keepLongWords inputList =
(List.concatMap String.words inputList)
|> List.filter (\item -> String.length item > 5)
{-| Version 3
-}
keepLongWords : List String -> List String
keepLongWords inputList =
inputList
|> List.concatMap String.words
|> List.filter (\item -> String.length item > 5)
Example 3: Maybe getting values?
https://ellie-app.com/3Ljrs7RhZCYa1
Problem 1: show only the smallest bat
Show only the smallest bat in the view using pattern matching
Problem 2: show only the largest bat
Show only the largest bat in the view using the `List.head` function
Problem 3: write-your-own `Maybe.map`
Write your own version of `Maybe.map`
Exercise 2: Maybes
https://ellie-app.com/3K8x8np6hbva1
Problem 1: break down a list
find the second item in a list at least two different ways
Problem 2: `Maybe.withDefault`
read the documentation for `Maybe.withDefault` and try to roll your own
Problem 3: explicit nulls
consider: what are the advantages of the `Maybe` pattern? how do you feel about it?
Questions? Break?
Section 6
Install Elm
Install elm-format
Syntax highlighting & such
this is too editor specific for me to feel comfortable making a suggestion. sorry!
https://guide.elm-lang.org/install.html
https://github.com/avh4/elm-format#installation-
developing locally
Example 1: Developing Locally
➜ Documents mkdir my-first-elm-project
➜ Documents cd my-first-elm-project
➜ my-first-elm-project elm init
Hello! Elm projects always start with an elm.json file. I can create them!
Now you may be wondering, what will be in this file? How do I add Elm files to
my project? How do I see it in the browser? How will my code grow? Do I need
more directories? What about tests? Etc.
Check out <https://elm-lang.org/0.19.0/init> for all the answers!
Knowing all that, would you like me to create an elm.json file now? [Y/n]: y
Okay, I created it. Now read that link!
➜ my-first-elm-project elm reactor
Go to <http://localhost:8000> to see your project dashboard.
Example 2: Developing Locally
➜ my-first-elm-project touch src/Main.elm
➜ my-first-elm-project subl .
module Main exposing (main)
import Browser
import Html exposing (..)
main =
Browser.sandbox
{ init = {}
, view = \model -> text "TODO"
, update = \msg model -> model
}
Exercise 1: Build a Thing!
Questions?
Thanks for coming!
Free Resources
- The Guide: https://guide.elm-lang.org/
- ElmBridge: https://elmbridge.github.io/curriculum/
Community
- Slack: elmlang.slack.com
- Reddit: https://www.reddit.com/r/elm/
- Discourse: https://discourse.elm-lang.org/
- Google group: https://groups.google.com/forum/#!forum/elm-discuss
- ... and for everything: http://elm-lang.org/community
Intro to Elm
By Tessa K
Intro to Elm
Introduction to the Elm programming language.
- 1,161