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.

Fearless refactoring
with elm

by Daniel Bachler (@danyx23)

this presentation is available at:

slides.com/danielbachler/fearless-refactoring-with-elm

25 minutes

the language

the architecture

the infrastructure

my experience so far

 

my pain points with js

  • No static typing means simple typos can lead to runtime errors
  • Deep changes to data structures in non-trivial JS projects need increadible amounts of diligence and attention
  • A big part of the unit & integration tests test really boring properties (does it correctly reject an undefined param, ...)

What is elm?

  • a functional programming language with static type checking that is compiled to JS
  • an FRP (functional reactive programming) runtime
  • designed to be easy to learn and good for web frontend dev
  • uses VDOM to efficiently update the DOM, similar to React

Elm, the language

  • Pure functional
  • Statically typed
  • Beginner friendly
function addNumbers(a, b) {
    return a + b;
}


// Whatever
addNumbers(4, "three");
addNumbers a b =
    a + b

-- Types are infered to be numbers

-- This is a compile time error
addNumbers 4 "three"

super friendly and helpful compiler

some personal favourite features

Union types

-- Union Type

type Gender 
    = Male
    | Female
    | Other String

personAGender = Male

personBGender = Other "Androgynous"

printGender gender =
    case gender of
        Male ->
            "male"
        Female ->
            "female"
        Other selfdefined ->
            selfdefined

Non-nullable values

-- There is no null, no undefined

type alias Person =
    { firstName : String
    , lastName : String
    , yearOfBirth : Int
    }

-- not possible
personA = { firstName = "Lao"
          , lastName = "Tse"
          , yearOfBirth = null
          }

birthYearToString person =
    toString person.yearOfBirth
-- instead:

type alias Person =
    { firstName : String
    , lastName : String
    , yearOfBirth : Maybe Int
    }


personA = { firstName = "Lao"
          , lastName = "Tse"
          , yearOfBirth = Nothing
          }

birthYearToString person =
    case person.yearOfBirth of
        Nothing ->
            "Unknown"
        Just age ->
            toString age

all values are immutable

x = 1

x = 2 -- compile error

x = x + 1 -- compile error

y = x + 1 -- ok

static typechecking

addNumbers : Int -> Int -> Int
addNumbers a b =
    a + b

birthYearToString : Person -> String
birthYearToString person =
    ...
  • The compiler always knows if your types check out or not
  • You can add Type Annotations so the compiler can tell you where you went wrong
  • Elm is always strongly typed, whether you add annotations or not (unlike Typescript, Flow, ...)
  • There is no "any" type like in TypeScript

 

All functions are pure

addNumbers : Int -> Int -> Int
addNumbers a b =
    a + b

result1 = addNumbers 1 2
result2 = addNumbers 1 2
result 1 == result 2 -- True

Calling the same function again with the same arguments will always return the same value, never have any side effects

function addNumbersWeird(a, b) {
    window.myGlobalState = window.myGlobalState || 0;
    return a + b + (window.myGlobalState++);
}

var result1 = addNumbersWeird(1, 2);
var result2 = addNumbersWeird(1, 2);
result1 == result2; // False

fearless refactoring

  • Compiler nags until all refactoring bugs are fixed
  • Say goodbye to "undefined is not a function"
  • No runtime errors in Elm

Unit tests can focus on logic

  • In Javascript, unit tests have to check for undefined etc
  • In Elm, the type system takes care of all of this
  • Unit tests in Elm can focus on behaviour and logic
  • Pure functions are super nice to test (little mocking required)

The Elm Architecture

Very similar to React without local state + Redux

Diagram by Evan Czaplicki

The Elm Architecture

See also André Staltz' great overview of unidirectional UI aproaches

The Elm Architecture

-- MODEL

type alias Model = Int


-- UPDATE

type Action = Increment | Decrement

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

    Decrement ->
      model - 1


-- VIEW

view : Signal.Address Action -> Model -> Html
view address model =
  div []
    [ button [ onClick address Decrement ] [ text "-" ]
    , div [ countStyle ] [ text (toString model) ]
    , button [ onClick address Increment ] [ text "+" ]
    ]


countStyle : Attribute
countStyle =
  style
    [ ("font-size", "20px")
    , ("font-family", "monospace")
    , ("display", "inline-block")
    , ("width", "50px")
    , ("text-align", "center")
    ]

-- Wire everything together
main =
  start
    { model = 0
    , update = update
    , view = view
    }

benefits

  • Model is single source of truth
  • Creating visual elements is done by running the Model through a pure view function
  • Side effects (XHRs, ...) are modelled as Tasks, handled by the runtime, results come back into the app as actions
  • Apps are well structured. All state modifications happen in the central update (or a function called from there)
  • Easy to replay whole UI sessions ( example)

The infrastructure

elm make

elm repl

elm package

package manager

  • Handles installation of packages
  • And publishing (inkl updates)
  • Automatically enforces SemVer (!!)

Interop with "native Javascript"

  • Incoming Ports (send messages from JS -> Elm)
  • Outgoing Ports (send messages from Elm -> JS)
  • Native modules (modules that use native JS - need to pass native review to be whitelisted)

Personal experience

  • Last spring, started work on a side project, a slideshow editor
  • Chose React for rendering (only pure components) with Redux to manage state (single source of truth) + Immutable.js
  • Many nice properties, but refactoring was still a pain. Also pretty verbose, immutable.js field access via strings, ...
  • Evaluated Typescript, Flow
  • Then took a closer look at elm and really liked it

+

  • General experience was very pleasant
  • Compiler is very helpful, many bugs can't even exist, code quality is higher
  • Refactoring with joy and confidence -> makes you do it more -> makes the code better
  • Community is friendly and helpful
  • Elm is small enough to learn it quickly, but still a very good stepping stone to other functional languages, esp. Haskell
  • Code reads well

-

  • Some rough edges (e.g. I use a script that deletes the compiler intermediate files before every compile because it would occasionally miss changed files)
  • Elm core team is small, some PRs to Docs etc linger for a long time (will hopefully get better with the new Elm Foundation)
  • Almost no support for running outside the Browser (=no server side rendering, ...)
  • Some trivial things in JS are a bit of a hassle in Elm, e.g. focusing a control (has to be done via port)

Would I do it again?

absolutely!

How to get started

  • try.elm-lang.org and   debug.elm-lang.org
  • elm-lang.org - great docs, read "The Elm Architecture"
  • Check out awesome-elm
  • try it for one widget of your app or a small side project
  • If you don't know any other functional languages, the first steps will be a bit rough ("What do you mean there are no loops?")
  • But it is very beginner friendly and a small, well-designed language
  • Used in production today by several companies

Should we do a hackathon style
meetup in Berlin?

Thank you!

by Daniel Bachler ( @danyx23 on twitter)

  

Rethinking Web Developement 

 

ELM

Who am I?

  Gabriel Grinberg

- Frontend dev @WixAnswers

- Elm e nthusiast

- Mozzie's proud owner -->

 

 

Disclaimer

  • I'm not an Elm expert
  • Very new to the F(R)P world
  • This talk is heavily opiniated

 

Let's face it..

JAvascript Sucks

Poor design

What started as  scripting  language that was hacked in just 2 weeks, for the browser, ended up being used to build massive web applications.

 

Since then, there are endless efforts by the community to fix the language's quirks, leading to tools fatigue.

 

Lack of Static typing & analysis

AKA the reason we have the famous JS WAT talk

console.log([]/(Math.sqrt('Bob' + 2))); // NaN :(

No Module system

<script src="../widgets/widgets_definition.config.js"></script>
<script src="../widgets/initial_widgets_list.val.js"></script>
<script src="../widgets/title-widget/title_widget.ctrl.js"></script>
<script src="../widgets/tickets-widget/tickets-widget.ctrl.js"></script>
<script src="../widgets/tasks-widget/tasks-widget.ctrl.js"></script>
<script src="../widgets/top-issues-widget/top-issues-widget.ctrl.js"></script>
<script src="../widgets/top-issues-widget/top-issues-widget-settings.ctrl.js"></script>
<script src="../widgets/statistics-widget/statistics-widget.ctrl.js"></script>
<script src="../widgets/statistics-widget/statistics-widget-settings.ctrl.js"></script>
<script src="../widgets/online-users-widget/online-users-widget.ctrl.js"></script>
<script src="../widgets/kb-list-widget/kb-list-widget.ctrl.js"></script>
...
...

Mutability & Side Effects

function calculateTotalPrice(products) {
    var totalPrice = products.reduce(function (currentTotal, product) {
      return currentTotal + product.price;
    });
    products.push('bob');
    initiateWorldWar4();
    return totalPrice;
}

Null

State Management

Result:

Tools Fatigue

SO, how can we solve it?

Elm TO The Rescue

wait.. another tool?!

What is ELM?

Elm is a purely functional language, designed to run in the browser, made by Evan Czaplicki.

 

It's not a Framework. Not a library. It's a whole different language.

Show us!

Show us some more!

Amazing compiler

If it compiles, it runs. No errors.

Highly addictive

  1. Static analysis

  2. Type checking and inference

  3. Informative error messages

Compiler Features

Compiler Demo

Say goodbye To devtools-debugging

High performance

Also, Elm's immutable objects are cached internally, leading to better memory management

Package Manager that enforces Semver (!!!)

It also enforces documentation for published packages

Reactive by design

Elm uses signals, what you might know as observables from RxJS for event handling, time, and more

Actually, in 0.17 it  has changed a lot! Signals are replaced by subscriptions and many things have been simplified

REACTIVE examples

MOre examples

Elm Architecture

Time Traveling debugger

FP features

Algebraic Data Types

type Tree = Empty
          | Leaf Int
          | Node Tree Tree
-- 

type TodoListAction = Add String
                    | Remove Int
                    | Update Int String
                    | Reset
head: List a -> String
head list = 
   case list of 
     x::[] -> "Singleton"
     x::xs -> "Not empty"
     [] -

Pattern Matching

type Fruit = Apple | Banana | Orange

firstBanana: List Fruit -> Maybe Fruit
firstBanana fruits =
     let 
       bananas = List.filter (\f -> f == Banana) fruits
     in
       case bananas of 
         banana::xs -> Just banana
         [] -> Nothing

Null Maybe

SIDE EFFECTS & tasks

Tasks make it easy to describe asynchronous operations that may fail, like HTTP requests or writing to a database. Tons of browser APIs are described as tasks in Elm

update : Action -> Model -> (Model, Effects Action)
update action model =
  case action of
    LoadTitle id ->
      (model, getTitle id)

    ShowError err ->
      ({model | error = err}, Effects.none)
      
    ShowTitle title -> 
      ({model | title = title}, Effects.none)

getTitle: String -> Effects Action
getTitle id = 
    Http.getString ("http://cool-api.com/" ++ id ++ "/title")
       |> Task.map ShowTitle
       |> (flip Task.onError) (\err -> Task.succeed (ShowError err))
       |> Effects.task

OK, but I want to use super-cool-library-thingie.js in elm. 

No probz. 

JS INterop using ports

Ports are a general purpose way to communicate with JavaScript. They let you send messages in and out of Elm so you can use JavaScript whenever you need to.

port addUser : Signal (String, UserRecord)
myapp.ports.addUser.send([
    "Tom",
    { age: 32, job: "lumberjack" }
]);

myapp.ports.addUser.send([
    "Sue",
    { age: 37, job: "accountant" }
]);

Redux

webdev is slowly  CONVERGING TO ELM

So, why aren't You using it yet in production?

Functional programming is           

SCARY

Beautiful

Elm Is Still Young, and unpopular

only a few companies use it in production

(Prezi, NoRedInk, CircuitHub, Gizra and a few more)

Probably that-library-you-really-need.js wasn't ported yet to elm

Final Words

  1. If you're new to FP, learn Elm!
  2. If Redux sounds like alien technology to you, learn Elm!
  3. If reactive concepts (RxJS) make your head twist, go learn Elm!
  4. If you wanna write better JS code, go learn Elm
  5. Once you all learn Elm, let's adopt Elm @Wix!

Questions?

References

Thanks!

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 ?

elm

By Dima Pikulin

elm

  • 1,293