Yet Another Introduction

Elm Lang

Live without side effects

What is Elm Lang

Elm is a functional language that compiles to JavaScript.

No combination of JS libraries can ever give you this, yet it is all free and easy in Elm.

No Runtime Exceptions *

Great Performance

Static types

Algebraic data types (ADT)

Immutability

Anonymous records

Parametric polymorphism 

Compile to Javascript

Why Elm?

Hello world


import Html exposing (span, text)
import Html.Attributes exposing (style)

main =
  span
    [style [("color", "red")]]
    [text "Hello, World!"]

Easy as ABC

Syntax

True  : Bool
False : Bool

42    : number  -- Int or Float depending on usage
3.14  : Float

'a'   : Char
"abc" : String

Literals

True && not (True || False)

(2 + 4) * (4^2 - 9)

"abc" ++ "def"

Typical manipulation of literals


(0, True, 'z', "abc")

(,) 1 2              == (1,2)
(,,,) 1 True 'a' []  == (1,True,'a',[])

Tuples

[1,2,3,4]
1 :: [2,3,4]
1 :: 2 :: 3 :: 4 :: []

['a', 'b', 'c']
["a", "b", "c"]

Lists

square n =
  n^2

hypotenuse a b =
  sqrt (square a + square b)

distance (a,b) (x,y) =
  hypotenuse (a-x) (b-y)

Functions

multiply a b = a * b

multiplyByThree = multiply 3

Partial Function Application

Operators are Functions Too

(++) [1, 2, 3] [4, 5, 6]

List.foldl (*) 1 [1, 2, 3, 4, 5]

Union Types

Type Annotation

-- function name : 1st arg type -> 2nd arg type -> return type
fnc : Int -> List Int -> Int

type Movement = Right | Left | Stop

type Maybe a = Just a | Nothing

type Result e a = Failure e | Success a

type Tree a = Tree (Tree a) a (Tree a) | Leaf

point =                         -- create a record
  { x = 3, y = 4 }

point.x                         -- access field

List.map .x [point,{x=0,y=0}]   -- field access function

{ point | x = 6 }               -- update a field

{ point |                       -- update many fields
    x = point.x + 1,
    y = point.y + 1
}

dist {x,y} =                    -- pattern matching on fields
  sqrt (x^2 + y^2)

type alias Location =           -- type aliases for records
  { line : Int
  , column : Int
  }

Syntax. Records


primitiveCount number =
  case number of
    1 -> "one"
    2 -> "two"
    3 -> "three"
    4 -> "four"
    _ -> "many"


case maybe of
  Just xs -> xs
  Nothing -> []


case xs of
  hd::tl -> Just (hd,tl)
  []     -> Nothing


case n of
  0 -> 1
  1 -> 1
  _ -> fib (n-1) + fib (n-2)

Pattern Matching in Case Expression


module MyModule exposing (..)

-- qualified imports
import List                    -- List.map, List.foldl
import List as L               -- L.map, L.foldl

-- open imports
import List exposing (..)               -- map, foldl, concat, ...
import List exposing ( map, foldl )     -- map, foldl

import Maybe exposing ( Maybe )         -- Maybe
import Maybe exposing ( Maybe(..) )     -- Maybe, Just, Nothing
import Maybe exposing ( Maybe(Just) )   -- Maybe, Just

Syntax. Modules

Let's practice a little bit

The Elm Architecture

The Basic Pattern

The logic of every Elm program will break up into three cleanly separated parts

Model

Update

View

Beginner program

Beginner program


import Html exposing (Html, beginnerProgram)

main : Program Never model msg
main =
  beginnerProgram
  { model = ...  -- : model
  , view = ...   -- : model -> Html msg
  , update = ... -- : msg -> model -> model
  }

import Html exposing (text)

main =
  Html.beginnerProgram
  { model = ()
  , view = always (text "Hello World!")
  , update = always identity
  }

--  always : a -> b -> a
--  identity : a -> a

Beginner program example

Beginner program example


import Html exposing (text, div, button)
import Html.Events exposing (onClick)

type Msg = Inc | Dec

model = 0

view model = div []
  [ button [ onClick Dec ] [ text "-" ]
  , text <| toString model
  , button [ onClick Inc ] [ text "+" ] ]

update msg model =
  case msg of
    Inc -> model + 1
    Dec -> model - 1

main = Html.beginnerProgram
  { model = model
  , view = view
  , update = update
  }

Beginner program 

can't control side effects

Side effects

  • Random value
  • Http requests
  • Time
  • Websockets communication
  • Mouse behavior
  • etc.

Program

Program


import Html exposing (program)

program :
  { init : (model, Cmd msg)
  , view : model -> Html msg
  , update : msg -> model -> (model, Cmd msg)
  , subscriptions : model -> Sub msg
  }
  -> Program Never model msg

Program Example with Sub usage


type alias Model = Time

init : (Model, Cmd Msg)
init =
  (0, Cmd.none)


type Msg
  = Tick Time


update : Msg -> Model -> (Model, Cmd Msg)
update msg model =
  case msg of
    Tick newTime ->
      (newTime, Cmd.none)


subscriptions : Model -> Sub Msg
subscriptions model =
  Time.every second Tick


view : Model -> Html Msg
view model =
  Html.text (toString model)

Program Example with Cmd usage


type alias Model = Int

type Msg
    = GenerateNumber
    | SetNumber Int


update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
    case msg of
        GenerateNumber ->
            ( model, Random.generate SetNumber (Random.int 1 6) )

        SetNumber number ->
            ( number, Cmd.none )


view : Model -> Html Msg
view model =
    div []
        [ h1 [] [ text (toString model) ]
        , button [ onClick GenerateNumber ] [ text "Generate" ]
        ]

But what about complex Applications?

We do not think in terms of reusable components. 

Instead, we focus on reusable functions. It is a functional language after all!

elm-repl — play with Elm expressions
elm-reactor — get a project going quickly
elm-make — compile Elm code directly
elm-package — download packages

Elm Tooling

Elm package repository (semver guarantee)

Time traveling debugger

Elm Ecosystem


$ elm-make Main.elm --output elm.js

Elm Embeding


<div id="elm-code-is-loaded-here"></div>

<script src="elm.js"></script>
<script>
  Elm.Main.embed(document.getElementById("elm-code-is-loaded-here"));
</script>

Elm Bundle

Framework sizes

$ ls -lhS
566K Jan  4 22:03 angular2.min.js
563K Jan  4 22:05 angular2.0.0-beta.0-all.umd.min.js
486K Jan  4 21:50 ember.1.13.8.min.js
435K Jan  4 21:48 ember.2.2.0.min.js
205K Jan  4 22:06 angular2.0.0-beta.0-Rx.min.js
144K Jan  4 21:59 react-with-addons-0.14.5.min.js
143K Jan  4 21:46 angular.1.4.5.min.js
132K Jan  4 21:56 react-0.14.5.min.js
121K Jan  4 21:35 angular.1.3.2.min.js
5.3K Jan  4 22:00 redux-3.0.5.min.js
706B Jan  4 21:57 react-dom-0.14.5.min.js
63K  Oct 13 03:02 vue-2.0.3.min.js

# 2017
91K  Dec 27 12:24 react-dom-16.2.0.production.min.js
6.5K Dec 27 12:22 react-16.2.0.production.min.js
$ elm-make Main.elm --output=main.js
$ uglifyjs ./main.js -o main.min.js -c -m
$ ls -lhS
189K Apr  7 15:32 main.js
 65K Apr  7 15:37 main.min.js

Hello world Elm App size

Resources

Workshop time!