The Elm language and ecosystem

Thomas Brisbout

Freelance JS developer

 @tbrisbout

Elm Paris Meetup / 2016-03-23

Front-End in 2016

Elm

What is elm ?

  • Pure functional
  • Immutable
  • Static Type System
  • No runtime errors
  • use Virtual-DOM

Yet another language that compile to JS ?

Simple example

import Html

main = Html.text "Hello World"

Get started

$ npm install -g elm
...
$ elm-repl
---- elm repl 0.16.0 -----------------------------------------------------------
 :help for help, :exit to exit, more at <https://github.com/elm-lang/elm-repl>
--------------------------------------------------------------------------------
> 1 + 1
2 : number
> 

Syntax

Basics

-- Boolean
True  : Bool
False : Bool
-- Boolean
True  : Bool
False : Bool

42    : number  -- Int or Float depending on usage
3.14  : Float
-- Boolean
True  : Bool
False : Bool

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

'a'   : Char
"abc" : String

-- multi-line String
"""
This is useful for holding JSON or other
content that has "quotation marks".
"""

Functions

Function Definition

-- anonymous function
(\ name -> "hello " ++ name)
-- anonymous function
(\ name -> "hello " ++ name)

-- named function
sayHello name = "hello " ++ name
-- anonymous function
(\ name -> "hello " ++ name)

-- named function
sayHello name = "hello " ++ name

-- function application
msg = sayHello "meetup" -- "hello meetup"

Function Type

sayHello : String -> String
sayHello name = "hello " ++ name

Function Type


add x y = x + y
add : number -> number -> number
add x y = x + y

Functions in Elm take one argument

Functions are curried

add x y = x + y

addOne = add 1

addOne 2 -- returns 3

-- The following are equivalent
add 3 4
(add 3) 4

Piping: Chaining functions

Html.text (String.repeat 3 (String.toUpper "Hello ! ")

HELLO ! HELLO ! HELLO !

Html.text (String.repeat 3 (String.toUpper "Hello ! ")

Html.text <| String.repeat 3 <| String.toUpper "Hello ! "
Html.text (String.repeat 3 (String.toUpper "Hello ! ")

Html.text <| String.repeat 3 <| String.toUpper "Hello ! "

"Hello !"
Html.text (String.repeat 3 (String.toUpper "Hello ! ")

Html.text <| String.repeat 3 <| String.toUpper "Hello ! "

"Hello !"
  |> String.toUpper
Html.text (String.repeat 3 (String.toUpper "Hello ! ")

Html.text <| String.repeat 3 <| String.toUpper "Hello ! "

"Hello !"
  |> String.toUpper
  |> String.repeat 3
Html.text (String.repeat 3 (String.toUpper "Hello ! ")

Html.text <| String.repeat 3 <| String.toUpper "Hello ! "

"Hello !"
  |> String.toUpper
  |> String.repeat 3
  |> Html.text

Function composition

double x = x * 2

addOne x = x + 1

(double >> addOne) 2 -- 5

(double << addOne) 2 -- 6

Data Structures

Lists

-- Every element in a list must have the same type.
["the", "quick", "brown", "fox"]

list = [1, 2, 3, 4]
listFromRange = [1..4]
listByAppending = [1, 2] ++ [3, 4]
listByPrepending = 1 :: 2 :: 3 :: 4 :: []
-- Every element in a list must have the same type.
["the", "quick", "brown", "fox"]

list = [1, 2, 3, 4]
listFromRange = [1..4]
listByAppending = [1, 2] ++ [3, 4]
listByPrepending = 1 :: 2 :: 3 :: 4 :: []

-- All classical methods are available
List.map (\ n -> n + 1) list -- [2,3,4,5]

List.filter (\ n -> n > 2) list --[3,4]

Tuples

("elm", 42)

fst ("elm", 42) -- "elm"
snd ("elm", 42) -- 42

error = (404, "Not found")

Records

person = 
  { firstName = "John"
  , lastName = "Doe" 
  }

person.firstName -- "John"

.firstName person -- "John"

.firstName { firstName = "Jane" } -- "Jane" 

Records

person = 
  { firstName = "John"
  , lastName = "Doe" 
  }

{ person |
  firstName = "George" }

-- { firstName = "George"
-- , lastName = "Doe" 
-- }

Records

person = 
  { firstName = "John"
  , lastName = "Doe",
  , age = 22
  }

canDrinkAlcohol {age} =
  age > 18

canDrinkAlcohol person -- True

Type aliases

createPerson : String -> String ->
  { firstName : String, lastName : String }
createPerson first last =
  { firstName = first
  , lastName = first
  }
type alias Person =
   { firstName : String
   , lastName : String 
   }

createPerson : String -> String -> Person
createPerson first last =
  { firstName = first
  , lastName = first
  }

Union Types

type Direction =
  North | South | East | West


type Answer = Yes | No | Other String

Conditionals

if key == 40 then
    n + 1

else if key == 38 then
    n - 1

else
    n

-- By the way, there 
-- is no "Truthy" of "Falsy"

Switch Case

type Shape
  = Circle Float
  | Rectangle Float Float


area : Shape -> Float
area shape =
  case shape of
    Circle radius ->
      pi * radius ^ 2

    Rectangle height width ->
      height * width

Module System

Imports

-- Qualified imports
import Html
import Html.Attributes

main = Html.div "test"
-- exposing single identifiers
import Html exposing (div, h1, p)

-- exposing everything
import Html.Attributes exposing (..)

-- import alias
import HelperFunctions as Utils

Exports

-- default module definition
module Main where

-- custom module exporting everything
module Foo (..) where

-- custom module exporting only 
-- the specified types and functions
module Bar (SomeType, someFunction) where

Signals

AKA the `R` in FRP

Signals are value that changes over time

Mouse.position

Keyboard.presses

Tooling

elm-make

Compile elm to js

  • Generate index.html by default
  • elm-make --output elm.js Main.elm

Hard to find typos

type alias Person =
  { firstName : String
  , lastName : String
  , birthDate : String
  }


john : Person
john =
  { firstName = "John"
  , lastName = "Doe"
  , brithDate = "1980-01-01"
  }

elm-reactor

elm-package

Init Project

$ elm package install
Some new packages are needed. 
Here is the upgrade plan.

  Install:
    elm-lang/core 3.0.0

Do you approve of this plan? (y/n) y
Downloading elm-lang/core
Packages configured successfully!

Install dependency

$ elm-package install evancz/elm-html
To install evancz/elm-html I would 
like to add the following
dependency to elm-package.json:

    "evancz/elm-html": "4.0.2 <= v < 5.0.0"

May I add that to elm-package.json for you? (y/n) y

Some new packages are needed. Here is the upgrade plan.

  Install:
    evancz/elm-html 4.0.2
    evancz/virtual-dom 2.1.0

Do you approve of this plan? (y/n) y
Downloading evancz/elm-html
Downloading evancz/virtual-dom
Packages configured successfully!

Diff in API

$ elm-package diff evancz/elm-html 3.0.0 4.0.0 
Comparing evancz/elm-html 3.0.0 to 4.0.0...
This is a MAJOR change.

------ Changes to module Html.Attributes - MAJOR ------

    Removed:
        boolProperty : String -> Bool -> Attribute
        stringProperty : String -> String -> Attribute


------ Changes to module Html.Events - MINOR ------

    Added:
        type alias Options =
            { stopPropagation : Bool, preventDefault : Bool }
        defaultOptions : Html.Events.Options
        onWithOptions : String -> Html.Events.Options 
         -> Json.Decode.Decoder a 
         -> (a -> Signal.Message) -> Html.Attribute

Custom loaders

elm-oracle

elm-format

Autoformat code

import Html.Events exposing (onClick)

type alias Model = Int

init : Int -> Model
init count = count

type Action = Increment | Decrement | Reset

update : Action -> Model -> Model
update action model =
  case action of
    Increment ->
      model + 1
    Decrement ->
      model - 1
    Reset ->
      0
import Html.Events exposing (onClick)


type alias Model =
  Int


init : Int -> Model
init count =
  count


type Action
  = Increment
  | Decrement
  | Reset


update : Action -> Model -> Model
update action model =
  case action of
    Increment ->
      model + 1

    Decrement ->
      model - 1

    Reset ->
      0

elm-test

Unit test in Elm

tests : Test
tests = 
  suite "A Test Suite"
    [ test "Addition" (assertEqual (3 + 7) 10)
    , test "String.left" (assertEqual "a" (String.left 1 "abcdefg"))
    , test "This test should fail" (assert False)
    ]
Successfully compiled TestRunner.elm
Running tests...
  1 suites run, containing 3 tests
  0 suites and 2 tests passed
  1 suites and 1 tests failed

Test Suite: A Test Suite: FAILED
  Addition: passed.
  String.left: passed.
  This test should fail: FAILED. not True

How to learn

Online Editor

Official tutorial

The Elm Architecture

Great (paid) video course on Pragmatic Studio

Community

Who is using Elm (in Prod)

Who to follow

Questions ?

Made with Slides.com