Introduction to Elm 0.17

06/07/2016 - Cambridge DDD Nights

@doppioslash

+ClaudiaDoppioslash

www.lambdacat.com

About me

Functional Programmer & Game Developer

Peer Stritzinger GmbH

Functional and Failure Tolerant Programming for Embbedded, Industrial Control and Automotive

Table of Contents

 

  • What is cool about Elm?
  • Meet Elm
  • Elm Concepts
  • Structuring programs in Elm
  • Why use statically typed pure Functional languages?

What is cool about Elm?

Elm is a Functional Language for interactive applications.

 

  • Pure Functional Programming
  • Avoid NULL pointers
  • Escape callback hell
  • Focus on simplicity
  • Compiles to fast Javascript/Html/CSS
  • Gateway drug to strongly typed FP

What sort of language is Elm?

What sort of language is Elm?

Purely Functional

Eager

What sort of language is Elm?

Static Type System

What sort of language is Elm?

Small

What sort of language is Elm?

Compiles to Javascript, HTML, CSS

What sort of language is Elm?

Interoperates with Javascript while still being type safe

What sort of language is Elm?

Invented by Evan Czaplicki for his thesis

What sort of language is Elm?

Meant to be approachable

What sort of language is Elm?

Optimised for learning curve

What sort of language is Elm?

Optimised for good error messages

What sort of language is Elm?

No 'scary' terms like Monad

What sort of language is Elm?

The advantages of strongly typed FP, with a quicker learning time

What sort of language is Elm?

Gateway drug to other strongly typed FP languages

(Haskell, Purescript, F#, ...)

What sort of language is Elm?

In Production at

Elm Fundamentals

Elm Fundamentals

  • Subscriptions

  • Program

  • Tasks

  • Effects (Cmd)

  • Platform

  • Ports

Subscriptions

Subscriptions

Pretty much subscribing to events. 

e.g. Clock Ticks, Websockets

What kind of functions can we apply on subscriptions?

What kind of functions can we apply on subs?

map : (a -> msg) -> Sub a -> Sub msg

applies a function on a Sub

returns another, transformed, Sub

What kind of functions can we apply on signals?

subscribe to multiple Subs

batch : List (Sub msg) -> Sub msg

Program

Program

The main function has to be a Program.

Implemented in Javascript, pretty much equivalent to what start-app used to be.

Task

Task

Represents asynchronous effects that may fail, like HTTP requests.

Effects (Cmd)

Effects (Cmd)

When we need to do something that's not pure we describe it as an Effect/Cmd.

Described as data, then run through tasks.

Platform

Platform

Keep Elm not irreversibly tied to Javascript, everything that will require platform-specific code is broken off into Platform.

Ports (aka interop)

Ports (aka interop)

port check : String -> Cmd msg

app.ports.check.subscribe(function(word) {
    var suggestions = spellCheck(word);        app.ports.suggestions.send(suggestions);
});

Can get data of the specified type in, or out.

How do you structure programs in Elm?

The Functional Triforce

Maybe

Union Types

Pattern Matching

The Functional Triforce

Union Types

define the Model:

type Tile
    = Door Size
    | Column
    | BackGround BackGroundTile
    | Shadow ShadowTile

The Functional Triforce

Maybe

gets rid of NULL errors

type Maybe a 
    = Just a 
    | Nothing

The Functional Triforce

Pattern Matching

String.toInt : String -> Maybe Int

toMonth : String -> Maybe Int toMonth rawString = 
    case String.toInt rawString of
      Nothing -> 
         Nothing 
      Just n -> 
         if n > 0 && n <= 12 then Just n else Nothing

Elm Architecture

Elm is opinionated:

your program should fit the

Elm Architecture

Elm Architecture

Model

View

Update

Elm Architecture

Model =

the Data Structure we pass around

Model

type alias Model =
  { input : String
  , messages : List String
  }

Model

type alias Model =
  { input : String
  , messages : List String
  }

Type alias

Model

Type alias =

give name to a set of fields in a record

Record =

set of key value pairs

Model

type alias Model =
  { input : String
  , messages : List String
  }

A record (somewhat like an object in Js, but typechecked)

Model

init : (Model, Cmd Msg)
init =
  (Model "" [], Cmd.none)

Model

Type signature

init : (Model, Cmd Msg)
init =
  (Model "" [], Cmd.none)

Elm Architecture

Update =

the function that does the change of state 

Update

type Msg
  = Input String
  | Send
  | NewMessage String

Update

type Msg
  = Input String
  | Send
  | NewMessage String

Message is a Union Type

Update

update : Msg -> Model -> (Model, Cmd Msg)
update msg {input, messages} =
  case msg of
    Input newInput ->
      (Model newInput messages, Cmd.none)

    Send ->
      (Model "" messages, WebSocket.send "ws://echo.websocket.org" input)

    NewMessage str ->
      (Model input (str :: messages), Cmd.none)

 

Update

update : Msg -> Model -> (Model, Cmd Msg)
update msg {input, messages} =
  case msg of
    Input newInput ->
      (Model newInput messages, Cmd.none)

    Send ->
      (Model "" messages, WebSocket.send "ws://echo.websocket.org" input)

    NewMessage str ->
      (Model input (str :: messages), Cmd.none)

 

Pattern Matching

Update

update : Msg -> Model -> (Model, Cmd Msg)
update msg {input, messages} =
  case msg of
    Input newInput ->
      (Model newInput messages, Cmd.none)

    Send ->
      (Model "" messages, WebSocket.send "ws://echo.websocket.org" input)

    NewMessage str ->
      (Model input (str :: messages), Cmd.none)

 

Constructor

Update

Side Effects

update : Msg -> Model -> (Model, Cmd Msg)
update msg {input, messages} =
  case msg of
    Input newInput ->
      (Model newInput messages, Cmd.none)

    Send ->
      (Model "" messages, WebSocket.send "ws://echo.websocket.org" input)

    NewMessage str ->
      (Model input (str :: messages), Cmd.none)

 

Subscription =

updates every time there is a new event

Elm Architecture

Elm Architecture

subscriptions : Model -> Sub Msg
subscriptions model =
  WebSocket.listen "ws://echo.websocket.org" NewMessage

Elm Architecture

View =

the code that renders from the Model

View

view : Model -> Html Msg
view model =
  div []
    [ div [] (List.map viewMessage model.messages)
    , input [onInput Input] []
    , button [onClick Send] [text "Send"]
    ]


viewMessage : String -> Html msg
viewMessage msg =
  div [] [ text msg ]

Main

(where you wire everything up)

Elm Architecture

Main

main =
  Html.program
    { init = init
    , view = view
    , update = update
    , subscriptions = subscriptions
    }

Main

main =
  Html.program
    { init = init
    , view = view
    , update = update
    , subscriptions = subscriptions
    }

Wiring up the Program

Tools

Tools

  • Package Manager (elm-package)

  • Automatic Recompilation (elm-reactor)

  • Editor Extensions

Tools

Package Manager (elm-package)

  • enforced semantic versioning

  • central package repository package.elm-lang.com (also hosts the docs)

  • no way to include repos outside of package.elm-lang.com

Tools

Automatic recompilation

 (elm-reactor)

  • Used to be the debugger

  • For 0.17 only does automatic recompilation of code

Tools

Editor Extensions

  • Atom

  • Emacs

  • LightTable

  • Sublime Text

Tools

Emacs (my setup)

  • elm-mode

  • flycheck

  • company

  • elm-oracle (broken)

Why use statically typed pure Functional languages?

Why it's worth to use new language research

No runtime exceptions

Why it's worth to use new language research

No race conditions

Why it's worth to use new language research

Better tools

Why it's worth to use new language research

Less code

Why it's worth to use new language research

Ease of parallelisation

How is Elm different from Haskell/Purescript?

How is Elm different from Haskell/Purescript?

Purescript is a new Strongly Typed Functional language that targets Javascript

How is Elm different from Haskell/Purescript?

Haskell is a Strongly Typed Functional language that targets native & more platforms

How is Elm different from Haskell/Purescript?

Elm is against higher abstractions

(e.g. no type classes)

How is Elm different from Haskell/Purescript?

Purescript has more flexible Javascript interop

How is Elm different from Haskell/Purescript?

An Elm program has to fit the Elm Architecture

(which is good if it fits, less if it doesn't. You don't have to conform to a specific architecture in Purescript/Haskell)

A few words of caution

A word of caution

Native modules

There is no path to get a library that wraps a javascript library on elm-package (e.g. elm-d3)

A word of caution

Elm is still experimental

Elm is still subject to big changes, expect to have to rewrite some of your code with a new version.

A word of caution

Elm lacks a roadmap

There are beta previews, and you can keep up by looking at the changes in the compiler

A word of caution

Your program should fit the Elm Architecture

Elm is very opinionated and going against the grain will result in pain (been there, done that)

A word of caution

The design is only up to Evan

So if you want to contribute to, say, the compiler you'll find a bottleneck there.

Once upon a time there was FRP

Once upon a time there was FRP

0.17 abandoned FRP, to obtain a better learning curve

If you see terms such as Signal, Mailbox, Address you're looking at Elm < 0.17.

elm-lang.org/docs

@elmlang

#elmlang <- twitter hashtag

elmlang.herokuapp.com <- get a Slack invite here

Where to learn Elm?

lambdacat.com

@lambda_cat

Read LambdaCat!

Introduction to Elm 0.17

By Claudia Doppioslash

Introduction to Elm 0.17

  • 3,459