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!

build something! I don't have any requirements for you. Please explore & play & ask me questions if you have them.


ideas if you need them (you probably won't finish these in the time remaining):
- todo app (for example, see todomvc)
- tic tac toe
- game of life (about)
- cat picture gallery

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,063