Introduction to Elm 0.17
by @doppioslash
06/07/2016 - Cambridge DDD Nights
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
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,726