Welcome!

Elm 101.5 Workshop

What is Elm?

Elm is a purely functional,

declarative programming language

for UI development,

built on functional reactive properties.

Answer the
following questions

  • What is The Elm Architecture (TEA)?

  • How can we use TEA?

  • What about components? 

...and hopefully ignite your curiosity!

Some Basic Syntax

Records

type alias X = 
  { a : Int
  , b : String }


foo : X 
foo = { a = 3
      , b = "wowzers" }

bar : X
bar = { foo | a = 5 }


bar == { a = 5
       , b = "wowzers" }

Function Anatomy

foo : Int -> Int -> Int
foo x y = x + x + y
// scala
def foo(x:Int)(y:Int):Int = x + x + y

// es6
const foo = x => y => x + x + y

// c#
Func<int, Func<int, int>> foo = x => y => x + x + y;

Lambdas

(\x -> x * x)
// scala
(x:Int => x * x)

// es6
(x => x * x)

// es5
(function(x){ return x * x; })

// math
λx. x * x

++ Operator

4 |> foo == foo 4
4 |> (\x -> x + 4) |> toString == "8"

|> Operator

[1,2] ++ [3,4] == [1,2,3,4]
"hi" ++ " " ++ "there" == "hi there"

Curry

foo : Int -> String -> String

foo 3 : String -> String

foo 3 "bar" : String

TEA has 5 parts

2 Types

Msg

The Type of discrete events in our application.

Model

Our single source of truth.

In TEA all application state resides on a single Model.

3 terms (values)

init/model

The initial Model
of our application.

init : Model
init:Modelinit : Model

update

The core logic.

Update "steps" our application forward based on Msgs.

update : Msg \rightarrow Model \rightarrow Model
update:MsgModelModelupdate : Msg \rightarrow Model \rightarrow Model

view

Display function.

The Html in the view may produce
Msg's that will then flow
through our application.

view : Model \rightarrow Html \,\, Msg
view:ModelHtmlMsgview : Model \rightarrow Html \,\, Msg

Let's take a fictitious election,

and see how we might model it using TEA.

Elm Runtime

Real World

type Msg
    = SummerWheatley
    | PedroSanchez

type alias Model = 
    { summerWheatley : Int
    , pedroSanchez : Int }


init : Model
init = 
    { summerWheatley = 0
    , pedroSanchez = 0 }



update : Msg -> Model -> Model 
update msg model = 
    case msg of 
        
          SummerWheatley -> 
            { model | 
              summerWheatley = model.summerWheatley + 1 }
        
          PedroSanchez ->
            { model | 
              pedroSanchez = model.pedroSanchez + 1 }



view : Model -> Html Msg
view model = div []
    [ text "Vote for:"
    , button [ onClick SummerWheatley ] [ text "Wheatley" ]
    , button [ onClick PedroSanchez   ] [ text "Sanchez" ] 
    ]

Renderer

Fold

State

Elm Runtime

Real World

type Msg
    = SummerWheatley
    | PedroSanchez

type alias Model = 
    { summerWheatley : Int
    , pedroSanchez : Int }


init : Model
init = 
    { summerWheatley = 0
    , pedroSanchez = 0 }



update : Msg -> Model -> Model 
update msg model = 
    case msg of 
        
          SummerWheatley -> 
            { model | 
              summerWheatley = model.summerWheatley + 1 }
        
          PedroSanchez ->
            { model | 
              pedroSanchez = model.pedroSanchez + 1 }



view : Model -> Html Msg
view model = div []
    [ text "Vote for:"
    , button [ onClick SummerWheatley ] [ text "Wheatley" ]
    , button [ onClick PedroSanchez   ] [ text "Sanchez" ] 
    ]

Renderer

Fold

State

Model

Elm Runtime

Real World

type Msg
    = SummerWheatley
    | PedroSanchez

type alias Model = 
    { summerWheatley : Int
    , pedroSanchez : Int }


init : Model
init = 
    { summerWheatley = 0
    , pedroSanchez = 0 }



update : Msg -> Model -> Model 
update msg model = 
    case msg of 
        
          SummerWheatley -> 
            { model | 
              summerWheatley = model.summerWheatley + 1 }
        
          PedroSanchez ->
            { model | 
              pedroSanchez = model.pedroSanchez + 1 }



view : Model -> Html Msg
view model = div []
    [ text "Vote for:"
    , button [ onClick SummerWheatley ] [ text "Wheatley" ]
    , button [ onClick PedroSanchez   ] [ text "Sanchez" ] 
    ]

Renderer

Sanchez
Html Msg

Fold

State

Model
Wheatley

Our user carefully considers...

Elm Runtime

Real World

type Msg
    = SummerWheatley
    | PedroSanchez

type alias Model = 
    { summerWheatley : Int
    , pedroSanchez : Int }


init : Model
init = 
    { summerWheatley = 0
    , pedroSanchez = 0 }



update : Msg -> Model -> Model 
update msg model = 
    case msg of 
        
          SummerWheatley -> 
            { model | 
              summerWheatley = model.summerWheatley + 1 }
        
          PedroSanchez ->
            { model | 
              pedroSanchez = model.pedroSanchez + 1 }



view : Model -> Html Msg
view model = div []
    [ text "Vote for:"
    , button [ onClick SummerWheatley ] [ text "Wheatley" ]
    , button [ onClick PedroSanchez   ] [ text "Sanchez" ] 
    ]

Renderer

Sanchez

Fold

Msg

State

Model
Wheatley

Elm Runtime

Real World

type Msg
    = SummerWheatley
    | PedroSanchez

type alias Model = 
    { summerWheatley : Int
    , pedroSanchez : Int }


init : Model
init = 
    { summerWheatley = 0
    , pedroSanchez = 0 }



update : Msg -> Model -> Model 
update msg model = 
    case msg of 
        
          SummerWheatley -> 
            { model | 
              summerWheatley = model.summerWheatley + 1 }
        
          PedroSanchez ->
            { model | 
              pedroSanchez = model.pedroSanchez + 1 }



view : Model -> Html Msg
view model = div []
    [ text "Vote for:"
    , button [ onClick SummerWheatley ] [ text "Wheatley" ]
    , button [ onClick PedroSanchez   ] [ text "Sanchez" ] 
    ]

Renderer

Sanchez
Html Msg

Fold

State

Model
Wheatley

Elm Runtime

Real World

type Msg
    = SummerWheatley
    | PedroSanchez

type alias Model = 
    { summerWheatley : Int
    , pedroSanchez : Int }


init : Model
init = 
    { summerWheatley = 0
    , pedroSanchez = 0 }



update : Msg -> Model -> Model 
update msg model = 
    case msg of 
        
          SummerWheatley -> 
            { model | 
              summerWheatley = model.summerWheatley + 1 }
        
          PedroSanchez ->
            { model | 
              pedroSanchez = model.pedroSanchez + 1 }



view : Model -> Html Msg
view model = div []
    [ text "Vote for:"
    , button [ onClick SummerWheatley ] [ text "Wheatley" ]
    , button [ onClick PedroSanchez   ] [ text "Sanchez" ] 
    ]

Renderer

Sanchez
Html Msg

Fold

Msg

State

Model
Wheatley

Let's get started

What happened to Signals?

The Elm Architecture

is based on the fold-ability of
immutable streams called Signals.

 

Once the pattern was established, working with
Signals became mostly boilerplate.


Elm has since baked the
programming model into the runtime,
making Signals completely opaque!

What does all this buy us?

Code is deterministic, immutable,
referentially transparent,
and side effect free.

Purity

Run-time errors in

Elm are exceptionally rare.

 

(types and good design)

Safety

Since all Elm functions are pure,
testing behavior is trivial.

Testability

Elm applications
are fast and efficient.

Performance

Components are broken into small common abstractions, allowing for a high degree of re-use and control.

Modularity

Bad code is hard to compile.
Errors are helpful, and
sometimes absurdly helpful.

Developer Experience

Thank you everyone.

Elm Workshop

By fresheyeball

Elm Workshop

  • 1,893