ELM

or how I learned to

front-end development

Who am I?

Marco Perone

@marcoshuttle / m.perone@mvlabs.it

What is Elm?

Programming language

  • runs in the browser
  • functional
  • statically typed

Runs in the browser


elm make Main.elm
                    

Your new friend the compiler


-- NICE TO MEET YOU ---------------------------------------

Friendly error messages


message = "hello everybody!"

main = text mesage

-- NAMING ERROR -------------------------------------------

Cannot find variable `mesage`

7|   text mesage
          ^^^^^^
Maybe you want one of the following?

    message

No runtime exceptions

Functional programming

Function

A sequence of program instructions that perform a specific task, packaged as a unit

Function


function doSomething(arguments)
{
    result = someOperationOn(arguments);

    return result;
}

Function

Function

Function

Function

Example


var specialIndex = 'key';

function setSpecialIndex(object, value) {
    object[specialIndex] = value;

    return object;
}

In Elm


specialIndex = "key"

setSpecialIndex object index value =
    { object | index = value }

Immutability

State can not be modified after it is created

message = "hello everybody!"

message = "hello again!"

-- DUPLICATE DEFINITION -----------------------------------

Naming multiple top-level values `message` makes things
ambiguous. When you say `message` which one do you want?

8| message = "hello again!"
   ^^^^^^^
Find all the top-level values named `message` and do some
renaming. Make sure the names are distinct!

Static typing

The type of every expression is determined at compile type, before the application runs

addThree int = int + 3

addThree "4"

-- TYPE MISMATCH ------------------------------------------

The argument to function `addThree` is causing a mismatch.

8|   addThree "4"
              ^^^
Function `addThree` is expecting the argument to be:

    Int

But it is:

    String

Type inference


addThree : number -> number
addThree int = int + 3

addThree : Int -> Int
addThree int = int + 3

Semantic versioning

A sample application

Hanoi Towers

The Elm Architecture

Model

How could we model it?


type alias Disk = Int

type alias Model = ( List Disk, List Disk, List Disk )

What if...


model = ([1, 3, 5], [1, 2], [])

A better way


type Position
    = FirstPeg
    | SecondPeg
    | ThirdPeg

type alias Model = List Position

We keep track of...


type alias Model =
    { status : Hanoi.Model
    , from : Maybe Peg
    , to : Maybe Peg
    , message : Maybe String
    }

View


view : Model -> Html Msg
view model =
    div [ class "container" ]
        [ div [ class "pegs" ]
            [ div [ class "peg" ]
                [ ol [ class "pegList" ]
                    ( List.map viewDisk
                        fst ( disposition model.status )
                    )
                ]
            , ...


viewDisk : Int -> Html Msg
viewDisk i =
    li [ id ( "disk" ++ toString i ), class "disk" ] []

Update

Messages


type Msg
    = From ( Maybe Peg )
    | To ( Maybe Peg )
    | Error String
    | Move Peg Peg

View Updated


view : Model -> Html Msg
view model =
    ...
        div [ class "hanoi-controls" ]
        [ button
            [ onClick ( tryMove model ) ]
            [ text "Move" ]
        ]

tryMove : Model -> Msg
tryMove model =
    case ( model.from, model.to ) of
        ( Nothing, _ ) -> Error "Starting peg missing"
        ( _, Nothing ) -> Error "Ending peg missing"
        ( Just from, Just to ) -> Move from to

Update


update : Msg -> Model -> Model
update msg model =
    case msg of
        From maybePeg ->
            { model | from = maybePeg, message = Nothing }

        To maybePeg ->
            { model | to = maybePeg, message = Nothing }

        Error message ->
            { model | message = Just message }

        Move from to ->
            performMove model.status from to

TEA recap

Effects

Websockets

commands

Messages


type Msg
    = From ( Maybe Peg )
    | To ( Maybe Peg )
    | Error String
    | RequestMove Peg Peg
    | Move Peg Peg

Update


update : Msg -> Model -> ( Model, Cmd Msg )
update msg model =
    case msg of
        ...
        RequestMove from to ->
            let
                encodedJson =
                    encode 4
                        ( object
                            [( "from", int ( toInt from ))
                            ,( "to", int ( toInt to ))
                            ]
                        )
            in
                ( model, WS.send "ws://host" encodedJson )

subscriptions

Subscriptions


subscriptions : Model -> Sub Msg

Subscriptions


subscriptions : Model -> Sub Msg
subscriptions model =
    WS.listen "ws://host" decodeMessage

decodeMessage : String -> Msg

Thank you!

Resources

elm-lang.org

guide.elm-lang.org

www.elm-tutorial.org

www.elmcast.io

www.elmweekly.nl

groups.google.com/forum/#!forum/elm-discuss

elmlang.slack.com

SPEAKERS FEEDBACK!

Rate the talks!!! legacy.joind.in/19115

@marcoshuttle / m.perone@mvlabs.it