Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Let's learn Elm

Let's learn Elm

I had a talk about Elm-lang in our company. The main target is frontend engineer who is familiar to trendy MV* frameworks.

Yosuke Torii

July 01, 2015
Tweet

More Decks by Yosuke Torii

Other Decks in Programming

Transcript

  1. This slide is about... - What is Elm? - Why

    is Elm great? - For web-app developers × Type systems × Useful tools/libraries × For game developers × For FP developers
  2. What's Elm? - FRP(Functional Reactive Programming) - Haskell-like Syntax -

    No runtime errors - Compile to JavaScript main = span [class "welcome-message"] [text "Hello, World!"]
  3. a = 1 b = 1 c = a +

    b print c // => 2 Reactive Programming
  4. a = 1 b = 1 c = a +

    b print c // => 2 b = 2 print c // => ? Reactive Programming
  5. a = model(1) b = model(1) updateC = function() {

    c = a.value + b.value } a.onChange(updateC) b.onChange(updateC) updateC() I know the observer pattern!
  6. React's Virtual DOM Model Model DOM DOM DOM DOM VDOM

    VDOM VDOM VDOM Model update() render()
  7. React's Virtual DOM Model Model DOM DOM VDOM VDOM VDOM

    VDOM Model update() render() DOM DOM diff exists diff exists
  8. Declarative programming comes back! render: function() { return ( <div>

    <h3>TODO</h3> <TodoList items={this.state.items} /> <form onSubmit={this.handleSubmit}> <input onChange={this.onChange} value={this.state.text} /> <button>{'Add #' + (this.state.items.length + 1)}</button> </form> </div> ); }
  9. React + X Type-safety Architecture Flux Immutability Virtual DOM Reactivilty

    - Flow - Bacon.js - RxJS - Fluxible - Fluxxor + α - Immutable.js
  10. About Elm - born in Apr 2012 - ver 0.15

    - designed by Evan Czaplicki (Prezi) - http://elm-lang.org/ - https://groups.google.com/forum/#! forum/elm-discuss
  11. About Elm 0.15 Apr 2015 Tasks, better HTTP library 0.14

    Dec 2014 Package manager, parallel builds, JSON --- Jul 2014 elm-html http://evancz.github.io/elm-todomvc/ Graphics.Element Html http://elm-lang.org/examples/adventure
  12. Hello, world! import Html exposing (..) main : Html main

    = text "Hello, World!" text : String → Html
  13. Hello, world! import Html exposing (..) import Html.Attributes exposing (..)

    main : Html main = ul [class "grocery-list"] [ li [] [text "Pamplemousse"] , li [] [text "Ananas"] , li [] [text "Jus d'orange"] ] ul : List Attribute → List Html → Html li : List Attribute → List Html → Html class : String → Attribute
  14. Signals import Html exposing (..) import Mouse main : Signal

    Html main = Signal.map (\p -> text (toString p)) Mouse.position Mouse.position : Signal (Int, Int) Signal.map : (a → b) → Signal a → Signal b toString : a → String
  15. Signals (10, 20) Time main : Signal Html (15, 30)

    position : Signal (Int, Int) “(10, 20)” Time “(15, 30)” map
  16. Signals import Html exposing (..) import Mouse main : Signal

    Html main = Signal.map (\count -> text (toString count)) countClick countClick : Signal Int countClick = Signal.foldp (\clk count -> count + 1) 0 Mouse.clicks Mouse.clicks : Signal () Signal.foldp : (a → b → b) → b → Signal a → Signal b
  17. You might think FRP looks like... keydown timestamp errors fullname

    ajax formData firstName lastName enter letter tabIndex errorCount ok messages html click submit ok error reset inputs
  18. The Elm Architecture -- MODEL type alias Model = {

    ... } -- UPDATE type Action = Reset | ... update : Action -> Model -> Model update action model = case action of Reset -> ... ... -- VIEW view : Model -> Html view model = ...
  19. Model -- MODEL type alias Model = { tasks :

    List Task , field : String , uid : Int , visibility : String } type alias Task = { description : String , completed : Bool , editing : Bool , id : Int }
  20. Model newTask : String -> Int -> Task newTask desc

    id = { description = desc , completed = False , editing = False , id = id } emptyModel : Model emptyModel = { tasks = [] , visibility = "All" , field = "" , uid = 0 }
  21. Update -- UPDATE type Action = NoOp | UpdateField String

    | EditingTask Int Bool | UpdateTask Int String | Add | Delete Int | DeleteComplete | Check Int Bool | CheckAll Bool | ChangeVisibility String
  22. Update update : Action -> Model -> Model update action

    model = case action of NoOp -> model Add -> { model | uid <- model.uid + 1, field <- "", tasks <- if String.isEmpty model.field then model.tasks else model.tasks ++ [newTask model.field model.uid] } Delete id -> { model | tasks <- List.filter (\t -> t.id /= id) model.tasks } Check id isCompleted -> let updateTask t = if t.id == id then { t | completed <- isCompleted } else t in { model | tasks <- List.map updateTask model.tasks } ...
  23. View view : Address Action -> Model -> Html view

    address model = div [ class "todomvc-wrapper" , style [ ("visibility", "hidden") ] ] [ section [ id "todoapp" ] [ lazy2 taskEntry address model.field , lazy3 taskList address model.visibility model.tasks , lazy3 controls address model.visibility model.tasks ] , infoFooter ]
  24. View taskEntry : Address Action -> String -> Html taskEntry

    address task = header [ id "header" ] [ h1 [] [ text "todos" ] , input [ id "new-todo" , placeholder "What needs to be done?" , autofocus True , value task , name "newTodo" , on "input" targetValue (Signal.message address << UpdateField) , onEnter address Add ] [] ]
  25. Main main : Signal Html main = Signal.map (view actions.address)

    model model : Signal Model model = Signal.foldp update initialModel actions.signal actions : Signal.Mailbox Action actions = Signal.mailbox NoOp
  26. No unnecessary features! Keep it simple. Please support monad! Q:

    No. A: Really need type classes! Q: No. A: Higher-kinded types... Q: No. A:
  27. Nesting components type ButtonAction = Click (Int, Int) | Hover

    Float | NoOp type ContainerAction = Button ButtonAction | Checkbox CheckboxAction | Inputbox InputboxAction | NoOp Button.elm Main.elm
  28. Nesting components type alias ContainerModel = { button : ButtonModel

    , input : InputModel } init : ContainerModel init = { button = Button.init , input = Input.init } Main.elm
  29. Nesting components containerAddress : Address ContainerAction buttonAddress : Address ButtonAction

    buttonAddress = Signal.forwardTo containerAddress Button checkboxAddress : Address CheckboxAction checkboxAddress = Signal.forwardTo containerAddress Checkbox inputboxAddress : Address InputboxAction inputboxAddress = Signal.forwardTo containerAddress Inputbox Main.elm
  30. Stateful components? updateButton : ButtonAction -> ButtonState -> ButtonState updateButton

    action state = case action of Click -> { state | count <- state.count + 1 } update : Action -> Model -> Model update action model = case action of ButtonA a -> { model | buttonA <- updateButton a model.buttonA } ButtonB b -> { model | buttonB <- updateButton b model.buttonB } Main.elm Button.elm
  31. Is Elm ready for production? Yes! But needs more libraries

    for productivity. type Action = Wait | Contribute
  32. Conclusion - Elm is a FRP language - Elm also

    has a good architecture - Elm is ready to use