Slide 1

Slide 1 text

@sixty_north Elm Functional Programming for the Web 1 Austin Bingham @austin_bingham

Slide 2

Slide 2 text

2

Slide 3

Slide 3 text

3 The conference app! github.com/abingham/accu-2017-elm-app sixty-north.com/c/accu-2017/ Source Live

Slide 4

Slide 4 text

Agenda 4 What is Elm? 1 1 1 1 1 1 The Language 2 A Taste of Elm 3 The Elm Architecture 4 Talking to the Web 5 JavaScript Interop 6 A Tour of the ACCU 2017 App 7

Slide 5

Slide 5 text

5 What is Elm?

Slide 6

Slide 6 text

6 What is wrong with JavaScript?

Slide 7

Slide 7 text

Common complaints ‣ Hopeless type system ‣ Bolt-on modularity ‣ “flavor of the week” ‣ Requires tests, but hard to test ‣ Unexpected runtime errors ‣ Not really one language 7

Slide 8

Slide 8 text

8 How does Elm help?

Slide 9

Slide 9 text

An exercise in intelligent tradeoffs Elm directly addresses many JS deficiencies 9 Hopeless type system Bolt-on modularity “Flavor of the week” Requires tests, but hard to test Unexpected runtime errors Not really one language JavaScript Elm Haskell-inspired type system Intuitive native module system Prescribed patterns, “opinionated” Far fewer tests needed “no runtime exceptions” A single, BDFL-style language

Slide 10

Slide 10 text

10 Where does Elm fit in the world?

Slide 11

Slide 11 text

The same places as React, Angular, Backbone, et al. Elm is for developing web clients 11 Elm as part(s) of a larger page Elm controlling a full page or Elm

Slide 12

Slide 12 text

12 Who is behind Elm?

Slide 13

Slide 13 text

An active, fast-moving, and welcoming community Elm is an open-source project 13 elm-lang.org github.com/elm-lang/ groups.google.com/forum/#!forum/elm-discuss The result of Evan Czaplicki’s senior thesis

Slide 14

Slide 14 text

14 The Language

Slide 15

Slide 15 text

15 • Statically typed • Compiled (to JavaScript) • Immutable data structures • Type inferencing • Partial application, currying Haskell for web pages

Slide 16

Slide 16 text

Nothing surprising here Primitive types 16 42 : Int 3.14 : Float “Ulmaceae” : String ‘’ : Char True : Bool False : Bool

Slide 17

Slide 17 text

Optional typing, partial application, composition…the works! Functions 17 multiply x y = x * y multiply : number -> number -> number double = multiply 2 double : number -> number quadruple = double >> double quadruple : number -> number

Slide 18

Slide 18 text

Lists, arrays, set, and dictionaries Homogenous, iterable data types 18 import Array exposing (..) import Dict exposing (..) import Set exposing (..) list : List number list = [1, 2, 3] dict : Dict.Dict number String dict = Dict.empty |> Dict.insert 42 "answer" array : Array.Array number array = Array.fromList [2, 3, 4] set : Set.Set number set = Set.fromList [1, 1, 2, 2, 3, 3] removes duplicates fast indexing key-value mapping

Slide 19

Slide 19 text

The workhorse of Elm data modelling Records and type aliases 19 { firstName : String , lastName : String } type alias FullName = type alias User = { name : FullName , age : Int } me : User me = User (FullName "Austin" "Bingham") 42 use custom type getFirstName : User -> String getFirstName = .name >> .firstName “constructors” field accessors

Slide 20

Slide 20 text

A natural way to model weird (and not so weird) shaped data Union types and pattern matching 20 render : Shape -> String render shape = case shape of Circle radius -> "circle" Square length -> "square" RegularPolygon sides length -> "regular polygon" type Shape -- A circle has a radius = Circle Float -- A square has an edge length | Square Float -- Regular polygons have a number -- of sides and an edge length | RegularPolygon Int Float exhaustive

Slide 21

Slide 21 text

Easily and intuitively split code into rational pieces Modules and importing 21 module Loader exposing (load) load : String -> String load filename = . . . Loader.elm import Loader process = Loader.load "data.csv" import Loader as L process = L.load "data.csv" import Loader exposing (load) process = load "data.csv"

Slide 22

Slide 22 text

22 A Taste of Elm

Slide 23

Slide 23 text

23 The Elm Architecture

Slide 24

Slide 24 text

Model, messages, update, and view The Elm Architecture 24 update view Elm runtime in out model Cmd msg msg rendered/ HTML

Slide 25

Slide 25 text

…and the order in which I write them. The architecture in code… 25 -- MODEL type alias Model = { id: Int, ... } 1 The shape of the data -- VIEW view : Model -> Html Msg view = ... 2 How it looks -- UPDATE update : Msg -> Model -> (Model, Cmd Msg) update msg model = case msg of Reset -> ... ... -- MSG VOCABULARY type Msg = Reset | ... 3 How it changes

Slide 26

Slide 26 text

Your main function is what ties these parts together Some assembly required 26 import Html import Platform.Cmd import Platform.Sub main : Program Never Model Msg main = Html.program { init = ( initialModel, Platform.Cmd.none ) , view = view , update = update , subscriptions = \_ -> Platform.Sub.none } standard type for main flags your model your messages starting model initial “actions” your view your update messages from JavaScript

Slide 27

Slide 27 text

Different factories for different applications What is “Program”? 27 Platform.program A headless program without a view function A program with an HTML view A program with an HTML view and which calls update when the route changes Html.program Navigation.program main : Program Never Model Msg

Slide 28

Slide 28 text

Requesting work in JavaScript, and getting results Cmds vs. messages 28 Diagram from https://guide.elm-lang.org/architecture/effects/ Cmd ask the runtime to “do stuff” get notifications from the runtime “We create data that describes what we want to do, and the Elm Runtime does the dirty work.” —elm-lang.org

Slide 29

Slide 29 text

The magic that makes all of this fast Virtual DOM 29 div h1 ul li Virtual DOM div h1 ul li 1 Build the virtual DOM div h1 ul li

Slide 30

Slide 30 text

The magic that makes all of this fast Virtual DOM 30 div h1 ul li Virtual DOM div h1 ul li 2 Render the live DOM div h1 ul li

Slide 31

Slide 31 text

The magic that makes all of this fast Virtual DOM 31 div h1 ul li Virtual DOM div h1 ul li 3 Render the new virtual DOM li div h1 ul li old new

Slide 32

Slide 32 text

The magic that makes all of this fast Virtual DOM 32 div h1 ul li Virtual DOM div h1 ul li 4 Update DOM based on the diff li div h1 ul li li old new

Slide 33

Slide 33 text

And getting this speed is easier than with other frameworks Elm’s Virtual DOM is fast 33 http://elm-lang.org/blog/blazing-fast-html http://elm-lang.org/blog/blazing-fast-html-round-two

Slide 34

Slide 34 text

34 The Elm Architecture in Miniature

Slide 35

Slide 35 text

35 Talking to the web

Slide 36

Slide 36 text

HTTP requests are an example of actions that might fail The real world breaks sometimes 36 send : (Result Error a -> msg) -> Request a -> Cmd msg type Result error value = Ok value | Err error everything worked something went wrong translate a result to your vocabulary

Slide 37

Slide 37 text

This is a tricky spot for many new Elm programmers Decoding JSON 37 1 Start with primitive decoders 2 Combine them into more complex decoders 3 Extract fields from JSON structures 4 Construct records from decoded values Json.Decode.Decoder a int : Decoder Int list int : Decoder (List Int) field "prices" (list int) : Decoder (List Int) map Stock (field "prices" (list int)) : Decoder Stock Json.Decode.Pipeline

Slide 38

Slide 38 text

This is a tricky spot for many new Elm programmers Decoding JSON 38 1 Start with primitive decoders 2 Combine them into more complex decoders 3 Extract fields from JSON structures 4 Construct records from decoded values Json.Decode.Decoder a int : Decoder Int list int : Decoder (List Int) field "prices" (list int) : Decoder (List Int) map Stock (field "prices" (list int)) : Decoder Stock Json.Decode.Pipeline decodeString : Decoder a -> String -> Result String a

Slide 39

Slide 39 text

Generally much simpler! Encoding JSON 39 1 Convert primitive objects to Value objects 2 Convert aggregates of Values into Values 3 Encode Values into strings Json.Encode int : Int -> Value list : List Value -> Value encode : Int -> Value -> String

Slide 40

Slide 40 text

Generally much simpler! Encoding JSON 40 1 Convert primitive objects to Value objects 2 Convert aggregates of Values into Values 3 Encode Values into strings Json.Encode int : Int -> Value list : List Value -> Value encode : Int -> Value -> String encodeInts : List Int -> String encodeInts = List.map Json.Encode.int >> Json.Encode.list >> Json.Encode.encode 2

Slide 41

Slide 41 text

update Http.get Type-safe interaction with web servers and other services HTTP 41 type alias Data = { . . .} type Message = DataFetched (Result Http.Error Data) dataDecoder : Json.Decode.Decoder Data Elm runtime in out “http://data-service.com/ dataDecoder Http.send DataFetched Request Cmd Message Message

Slide 42

Slide 42 text

42 JavaScript Interop

Slide 43

Slide 43 text

Passing data to your app at startup Flags 43 Javascript var flags = { debug = True; connectionString = 'sqlite://test.db'; }; var Elm = . . . ; var mountNode = document.getElementById('main'); Elm.MyApp.embed(mountNode, flags); Elm type alias Flags = { debug : Bool , connectionString : String } main : Html.Program Flags Model Msg main = Html.programWithFlags { init = \flags -> . . . , view = view , update = update , subscriptions = . . . }

Slide 44

Slide 44 text

Sources of messages that you can listen to Subscriptions 44 type Msg = NewMessage String subscriptions : Model -> Sub Msg subscriptions model = WebSocket.listen "ws://echo.websocket.org" NewMessage main = Html.program { init = init , view = view , update = update , subscriptions = subscriptions } subscriptions must result in our message type specific message constructor subscribe in main

Slide 45

Slide 45 text

Javascript Elm Define “tunnels” for sending and receiving data to and from Javascript Ports 45 port module Spelling exposing (..) -- port for sending strings out to JavaScript port check : String -> Cmd msg -- port for listening for suggestions from JavaScript port suggestions : (List String -> msg) -> Sub msg Example taken from https://guide.elm-lang.org/interop/javascript.html var app = Elm.Spelling.fullscreen(); app.ports.check.subscribe(function(word) { var suggestions = spellCheck(word); app.ports.suggestions.send(suggestions); });

Slide 46

Slide 46 text

46 A Tour of the ACCU 2017 App

Slide 47

Slide 47 text

47

Slide 48

Slide 48 text

48 index.js

Slide 49

Slide 49 text

49 Main.elm

Slide 50

Slide 50 text

50 Model.elm

Slide 51

Slide 51 text

51 Msg.elm

Slide 52

Slide 52 text

52 Update.elm

Slide 53

Slide 53 text

53 Comms.elm

Slide 54

Slide 54 text

54 Json.elm

Slide 55

Slide 55 text

55 Routing.elm

Slide 56

Slide 56 text

56 Search.elm

Slide 57

Slide 57 text

57 Storage.elm

Slide 58

Slide 58 text

58 Asciidoc.elm

Slide 59

Slide 59 text

59 View.elm

Slide 60

Slide 60 text

Elm has a lot of potential, but you need to be aware of its rough edges Caveat Elm-ptor ‣ Language and core are evolving ‣ Best practices are far from settled ‣ Bus factor and mind share ‣ Tooling has room for improvement ‣ It’s just different 60

Slide 61

Slide 61 text

Links 61 github.com/abingham/elm-presentation-material Presentation code and examples github.com/abingham/jupyter-elm-kernel Jupyter kernel for Elm github.com/abingham/accu-2017-elm-app ACCU Schedule app

Slide 62

Slide 62 text

62 Don’t forget the put a (green) card in a box!

Slide 63

Slide 63 text

63 Thank you! @sixty_north Austin Bingham @austin_bingham