Tessa Kelly
twitter: @t_kelly9, github: @tesk9
NoRedInk
Helping teachers
teach grammar and writing
... using Elm
No Runtime Exceptions
Great Performance
logging values, crashing, time traveling
concat strings, type coercion, functions
comparisons, if/else expressions, handling cases
building a static view with elm/html
https://ellie-app.com/3K8f7626MXqa1
Change the view to use your name.
Modify your code to use string concatenation
Add a helper that returns an introduction string given a name
https://ellie-app.com/3K8x8np6hbva1
Say what kind of pets you do have
Modify your code to use string concatenation
Add & use a helper that returns a sentence like "I have 3 pet mice", where "mice" is the argument.
-- 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);
-- 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
https://ellie-app.com/3K8f7626MXqa1
Say how old you are in your introduction
Handle 1-year-old case using a case expression
Handle 1-year-old case with if/else expressions
https://ellie-app.com/3KjznK96brsa1
Modify your helper to accept an integer number of pets.
Handle 1-pet case using a case expression
Handle 1-pet case with an if/else expression
-- 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?
https://ellie-app.com/3KjVDZYwhtca1
Consider: what would happen if we accidentally passed the plural value into the singular slot?
-- 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
Browser.sandbox and the Elm Architecture
Html.Events.onClick
interactivity and the Elm Architecture
-- 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/
https://ellie-app.com/3KkLpMnypQTa1
Set up wiring for an interactive application
Increase the age
Consider: how might we support a second button that decreased the age?
https://ellie-app.com/3Km3mMN8nhfa1
Set up wiring for an interactive application
Acquire a new pet with every click
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
https://ellie-app.com/3KmdjnrNgmha1
records & type aliases
types & case expressions
building a more complex application
https://ellie-app.com/3KnjcvvJ3vCa1
Create key value pair mappings for name and for age
Update the age value
Replace the age integer model with a record-based model, to which we will be able to add more fields & state
https://ellie-app.com/3KnnF96VhcZa1
Create key value pair mappings for pet species and count
Update the pet value
Replace the count integer model with a record-based model, to which we will be able to add more fields & state
https://ellie-app.com/3KntTjq3GFBa1
Change the introduction helper to take the entire model. Use record deconstruction
Add a type annotation to `buildIntro`
Add a type alias for the model. Experiment with how this addition changes the error messages you might run into
https://ellie-app.com/3KnFkxw4WZ4a1
Change the helper to take the entire model. Use record deconstruction
Add a type annotation to `myPetsAre`
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?
-- 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 }
https://ellie-app.com/3KnQq5LfnFra1
Add a type annotation to the `update` function
Allow the user to change their username
What happens? Consider: what are our options?
-- 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
https://ellie-app.com/3Kp7xDn8YGqa1
Using a new, custom type, describe the possible state changes in the application
Use the new Msg type in the update function
Add a type annotation to the `view` code. What do you notice? How do you think `Html` works?
https://ellie-app.com/3KpcxMMZ8rZa1
Using a new, custom type, describe the possible state changes in the application
Use the new type in the update function
Consider: where else in the application might you want to use a custom type?
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/
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
https://package.elm-lang.org/
notZero number =
number /= 0
https://package.elm-lang.org/
find and read about Booleans in Elm. What do you notice about how they're modeled?
find and read about tuples in elm. When might you use a tuple? What does `mapFirst` do?
search for `map` in elm/core. Which modules include a `map` function? Why might this be?
➜ 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!
https://ellie-app.com/3Lc3vWS7FVna1
add some style attributes to make more pretty
yay libraries!
convert the `style` tags to use elm-css instead
https://ellie-app.com/3Lc8qsVGN4Ya1
install rtfeldman/elm-css & beautify
add animal pictures & customize your work! what other features do you want your pets page to have?
https://package.elm-lang.org/packages/mdgriffith/elm-ui/latest/
transforming a value with multiple functions
creating lists, mapping
de-structuring lists, `Maybe`s
composing with lists
https://ellie-app.com/3LcSHg4RtP7a1
show the species & picture of the first bat.
reuse a helper to show each bat
order the bats on the page by size
https://ellie-app.com/3LhYsYnhyC8a1
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.
https://ellie-app.com/3LhYvf29vpDa1
-- 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)
https://ellie-app.com/3Ljrs7RhZCYa1
Show only the smallest bat in the view using pattern matching
Show only the largest bat in the view using the `List.head` function
Write your own version of `Maybe.map`
https://ellie-app.com/3K8x8np6hbva1
find the second item in a list at least two different ways
read the documentation for `Maybe.withDefault` and try to roll your own
consider: what are the advantages of the `Maybe` pattern? how do you feel about it?
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
➜ 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.
➜ 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
}