(elm)troduction

An introduction to elm-lang

What is elm

  • 6 years old language (2012)
  • Compile to JS
  • Front-end focus
  • Simplicity focus
  • FRP focus

CHARACTERISTICS

  • Functional
  • ML syntax
  • Immutability
  • Pure functions
  • Strong type system, but:
    • No typeclasses
    • No higher kinded types
  • Functional reactive programming

DO I REALLY NEED TO LEARN A NEW LANGUAGE?

LET’S JUST USE JAVASCRIPT!

ES6 + Babel + Webpack + React + Redux + Immutable

Elm

           or                               or                                 or                                    or

Typescript           Gulp         Cycle.js + RxJS      seamless

Not even close

Elm Make

The compiler that talks to you

No Runtime Exceptions

No Runtime Exceptions

A little more syntax

-- isNotEven = not . isEven
isNotEven = not << isEven
isNotEven_ = isEven >> not

-- let lastChar = head $ toList $ reverse "foobar"
let lastChar = head <| toList <| reverse "foobar"

dot =
 scale 2 (move (20,20) (filled blue (circle 10)))

dot_ =
 circle 10
 |> filled blue
 |> move (20,20)
 |> scale 2

Records

carolina =
    { name = "Carolina de Jesus"
    , age = 62
    }

abdias =
    { name = "Abdias Nascimento"
    , age = 97
    }


people =
    [ carolina
    , abdias
    ]

carolina.name
.name carolina

List.map .name people
-- ["Carolina de Jesus", "Abdias Nascimento"]

ELM-REPL

Just a regular REPL

ELM-PACKAGE

The best package manager ever

ENFORCED SEMVER

ENFORCED SEMVER

AUTOMATIC CHANGELOG

ENFORCED DOCS

ELM REACTOR

Awesome development flow

Elm Reactor

  • Auto compile Elm
  • Hot-swapping
  • Time travel debugging

Example

THE ELM ARCHITECTURE

Model-View-Update

Model-View-Update

Concept Elm Redux
Application state Model State
Application events Message Action
Function that transforms the state Update Reducer

talk is cheap, show me the code

module Counter exposing (..)

import Html exposing (..)
import Html.Events exposing (onClick)
import Html.Attributes exposing (style)


-- MODEL

type Msg
    = Increment
    | Decrement


model : Int
model =
    0

...
Counter.elm
...

-- VIEW

view : Int -> Html.Html Msg
view model =
    div []
        [ button [ onClick Increment ] [ text "+" ]
        , br [] []
        , div [ countStyle ] [ text (toString model) ]
        , br [] []
        , button [ onClick Decrement ] [ text "-" ]
        ]


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

...
Counter.elm
...

-- UPDATE

update : Msg -> Int -> Int
update msg model =
    case msg of
        Increment ->
            model + 1

        Decrement ->
            model - 1
Counter.elm
module Main exposing (..)

import Html exposing (beginnerProgram)
import Counter exposing (model, view, update, Msg)


main : Program Never Int Msg
main =
    beginnerProgram { model = model, view = view, update = update }
Main.elm

Elm Runtime

Commands

Commands

Subscriptions

Subscriptions

invention or discovery?

try to escape the Elm Architecture, I dare you!

ELM-TEST

Only for checking what the compiler can’t

ELM TEST

module Example exposing (..)

import ElmTest exposing (..)


tests : Test
tests =
    suite "A Test Suite"
        [ test "Addition" <|
            assertEqual (3 + 7) 10
        , test "This test should fail" <|
            assert False
        ]

ELM TEST BDD STYLE

module ExampleBDD exposing (..)

import ElmTestBDDStyle exposing (..)
import Expect exposing (..)
import Test exposing (..)

tests : Test
tests =
    describe "Example Test"
        [ it "dds two numbers" <|
            expect (3 + 7) to equal 10
        , it "fails for non-sense stuff" <|
            expect True toBe False
        ]

JavaScript interop

Avoid it at all costs

From JS to ELM

myapp.ports.addUser.send([
    "Tom",
    { age: 32, job: "lumberjack" }
]);
myapp.ports.addUser.send([
    "Sue",
    { age: 37, job: "accountant" }
]);
-- port for listening for addUser from JavaScript
port addUser : (String, UserRecord -> msg) -> Sub msg

From ELM to JS

myapp.ports.requestUser.subscribe(databaseLookup);

function databaseLookup(user) {
    var userInfo = database.lookup(user);
    myapp.ports.addUser.send(user, userInfo);
}
-- port for sending strings out to JavaScript
port requestUser : String -> Cmd msg

JS INTEROP

DON'T USE THIS

Get your hands dirty

Thank You

(elm)troduction

By Henk

(elm)troduction

  • 171