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

Fluent Conf 2017: Tame the frontend with Elm

Fluent Conf 2017: Tame the frontend with Elm

Jeremy Fairbank

June 21, 2017
Tweet

More Decks by Jeremy Fairbank

Other Decks in Programming

Transcript

  1. Tame the frontend
    with Elm
    Jeremy Fairbank / @elpapapollo

    View Slide

  2. Software is broken.
    We are here to fix it.
    Say [email protected]

    View Slide

  3. Happiness

    View Slide

  4. View Slide

  5. ✓ Easier to write code
    ✓ Easier to write tests
    ✓ Easier to refactor

    View Slide

  6. elm

    View Slide

  7. No runtime exceptions in
    practice.

    View Slide

  8. No undefined is not a
    function

    View Slide

  9. Fast

    View Slide

  10. One framework.
    No fatigue.
    Update
    View
    Model
    Messages

    View Slide

  11. elm

    View Slide

  12. Functional

    View Slide

  13. greet name =
    "Hello, " ++ name
    greet "Fluent Conf"
    -- Hello, Fluent Conf

    View Slide

  14. greet name =
    "Hello, " ++ name
    greet "Fluent Conf"
    -- Hello, Fluent Conf

    View Slide

  15. greet name =
    "Hello, " ++ name
    greet "Fluent Conf"
    -- Hello, Fluent Conf

    View Slide

  16. greet name =
    "Hello, " ++ name
    greet "Fluent Conf"
    -- Hello, Fluent Conf
    Single
    Expression

    View Slide

  17. greet name =
    "Hello, " ++ name
    greet "Fluent Conf"
    -- Hello, Fluent Conf

    View Slide

  18. greet name =
    "Hello, " ++ name
    greet "Fluent Conf"
    -- Hello, Fluent Conf

    View Slide

  19. Pure Data in
    Data out

    View Slide

  20. Pure No side
    effects

    View Slide

  21. Pure Predictable
    and Testable!

    View Slide

  22. add x y =
    x + y
    add 2 3 == 5
    add 2 3 == 5
    add 2 3 == 5

    View Slide

  23. add x y =
    x + y
    add 2 3 == 5
    add 2 3 == 5
    add 2 3 == 5

    View Slide

  24. add x y =
    x + y
    add 2 3 == 5
    add 2 3 == 5
    add 2 3 == 5

    View Slide

  25. Expressive
    Terse and declarative code

    View Slide

  26. myList = [1, 2, 3, 4, 5]
    double n = n * 2
    doubleNumbers list =
    List.map double list
    doubleNumbers myList -- [2, 4, 6, 8, 10]

    View Slide

  27. myList = [1, 2, 3, 4, 5]
    double n = n * 2
    doubleNumbers list =
    List.map double list
    doubleNumbers myList -- [2, 4, 6, 8, 10]

    View Slide

  28. myList = [1, 2, 3, 4, 5]
    double n = n * 2
    doubleNumbers list =
    List.map double list
    doubleNumbers myList -- [2, 4, 6, 8, 10]

    View Slide

  29. myList = [1, 2, 3, 4, 5]
    double n = n * 2
    doubleNumbers list =
    List.map double list
    doubleNumbers myList -- [2, 4, 6, 8, 10]

    View Slide

  30. myList = [1, 2, 3, 4, 5]
    double n = n * 2
    doubleNumbers list =
    List.map double list
    doubleNumbers myList -- [2, 4, 6, 8, 10]

    View Slide

  31. myList = [1, 2, 3, 4, 5]
    double n = n * 2
    doubleNumbers list =
    List.map double list
    doubleNumbers myList -- [2, 4, 6, 8, 10]

    View Slide

  32. Curried Functions
    Building blocks

    View Slide

  33. add x y = x + y
    add 1 2 -- 3
    (add 1) 2 -- 3

    View Slide

  34. add x y = x + y
    add 1 2 -- 3
    (add 1) 2 -- 3

    View Slide

  35. add x y = x + y
    add 1 2 -- 3
    (add 1) 2 -- 3

    View Slide

  36. add x y = x + y
    add 1 2 -- 3
    (add 1) 2 -- 3
    New function created

    View Slide

  37. increment = add 1
    increment 2 -- 3
    increment 41 -- 42

    View Slide

  38. increment = add 1
    increment 2 -- 3
    increment 41 -- 42

    View Slide

  39. increment = add 1
    increment 2 -- 3
    increment 41 -- 42

    View Slide

  40. Pipes
    Expressive Chaining

    View Slide

  41. exclaim (greet (String.toUpper "Tucker"))
    greet name = "Hello, " ++ name
    exclaim phrase = phrase ++ "!"

    View Slide

  42. "Tucker"
    |> String.toUpper
    |> greet
    |> exclaim

    View Slide

  43. "Tucker"
    |> String.toUpper
    |> greet
    |> exclaim

    View Slide

  44. |> String.toUpper "Tucker"
    |> greet
    |> exclaim

    View Slide

  45. "TUCKER"
    |> greet
    |> exclaim

    View Slide

  46. |> greet "TUCKER"
    |> exclaim

    View Slide

  47. "Hello, TUCKER"
    |> exclaim

    View Slide

  48. |> exclaim "Hello, TUCKER"

    View Slide

  49. "Hello, TUCKER!"

    View Slide

  50. No Runtime
    Exceptions

    View Slide

  51. Strong
    Static
    Types
    life : Int
    life = 42
    greeting : String
    greeting = "Hello World"
    isTrue : Bool
    isTrue = True
    numbers : List Int
    numbers = [1, 2, 3]

    View Slide

  52. Strong
    Static
    Types
    life : Int
    life = 42
    greeting : String
    greeting = "Hello World"
    isTrue : Bool
    isTrue = True
    numbers : List Int
    numbers = [1, 2, 3]

    View Slide

  53. Strong
    Static
    Types
    life : Int
    life = 42
    greeting : String
    greeting = "Hello World"
    isTrue : Bool
    isTrue = True
    numbers : List Int
    numbers = [1, 2, 3]

    View Slide

  54. greet : String -> String
    greet name =
    "Hello, " ++ name
    add : Int -> Int -> Int
    add x y =
    x + y

    View Slide

  55. greet : String -> String
    greet name =
    "Hello, " ++ name
    add : Int -> Int -> Int
    add x y =
    x + y

    View Slide

  56. greet : String -> String
    greet name =
    "Hello, " ++ name
    add : Int -> Int -> Int
    add x y =
    x + y

    View Slide

  57. greet : String -> String
    greet name =
    "Hello, " ++ name
    add : Int -> (Int -> Int)
    add x y =
    x + y

    View Slide

  58. The argument to function `greet` is causing a mismatch.
    11| greet 42
    ^^
    Function `greet` is expecting the argument to be:
    String
    But it is:
    number
    Compile time static type checks

    View Slide

  59. Immutable Data
    Safe and Consistent

    View Slide

  60. dog : { name : String, age : Int }
    dog =
    { name = "Tucker"
    , age = 11
    }
    dog.name -- "Tucker"
    dog.age -- 11
    Records

    View Slide

  61. dog : { name : String, age : Int }
    dog =
    { name = "Tucker"
    , age = 11
    }
    dog.name -- "Tucker"
    dog.age -- 11
    Records

    View Slide

  62. dog : { name : String, age : Int }
    dog =
    { name = "Tucker"
    , age = 11
    }
    dog.name -- "Tucker"
    dog.age -- 11
    Records

    View Slide

  63. dog : { name : String, age : Int }
    dog =
    { name = "Tucker"
    , age = 11
    }
    dog.name -- "Tucker"
    dog.age -- 11
    Records

    View Slide

  64. haveBirthday dog =
    { dog | age = dog.age + 1 }
    dog = { name = "Tucker", age = 11 }
    olderDog = haveBirthday dog
    olderDog.age -- 12
    olderDog.name -- "Tucker"
    dog.age -- 11
    dog.name -- "Tucker"
    Create New Data

    View Slide

  65. haveBirthday dog =
    { dog | age = dog.age + 1 }
    dog = { name = "Tucker", age = 11 }
    olderDog = haveBirthday dog
    olderDog.age -- 12
    olderDog.name -- "Tucker"
    dog.age -- 11
    dog.name -- "Tucker"
    Create New Data

    View Slide

  66. haveBirthday dog =
    { dog | age = dog.age + 1 }
    dog = { name = "Tucker", age = 11 }
    olderDog = haveBirthday dog
    olderDog.age -- 12
    olderDog.name -- "Tucker"
    dog.age -- 11
    dog.name -- "Tucker"
    Create New Data

    View Slide

  67. haveBirthday dog =
    { dog | age = dog.age + 1 }
    dog = { name = "Tucker", age = 11 }
    olderDog = haveBirthday dog
    olderDog.age -- 12
    olderDog.name -- "Tucker"
    dog.age -- 11
    dog.name -- "Tucker"
    Create New Data

    View Slide

  68. haveBirthday dog =
    { dog | age = dog.age + 1 }
    dog = { name = "Tucker", age = 11 }
    olderDog = haveBirthday dog
    olderDog.age -- 12
    olderDog.name -- "Tucker"
    dog.age -- 11
    dog.name -- "Tucker"
    Create New Data

    View Slide

  69. haveBirthday dog =
    { dog | age = dog.age + 1 }
    dog = { name = "Tucker", age = 11 }
    olderDog = haveBirthday dog
    olderDog.age -- 12
    olderDog.name -- "Tucker"
    dog.age -- 11
    dog.name -- "Tucker"
    Create New Data

    View Slide

  70. Custom Types
    Domain-specific code

    View Slide

  71. type alias Dog =
    { name : String
    , age : Int
    , breed : Breed
    }
    type Breed
    = Sheltie
    | Poodle

    View Slide

  72. type alias Dog =
    { name : String
    , age : Int
    , breed : Breed
    }
    type Breed
    = Sheltie
    | Poodle

    View Slide

  73. type alias Dog =
    { name : String
    , age : Int
    , breed : Breed
    }
    type Breed
    = Sheltie
    | Poodle
    Union Type

    View Slide

  74. dog : Dog
    dog =
    { name = "Tucker"
    , age = 11
    , breed = Sheltie
    }

    View Slide

  75. dog : Dog
    dog =
    { name = "Tucker"
    , age = 11
    , breed = Sheltie
    }

    View Slide

  76. dog : Dog
    dog =
    { name = "Tucker"
    , age = 11
    , breed = Sheltie
    }

    View Slide

  77. No null or
    undefined

    View Slide

  78. type Maybe a
    = Just a
    | Nothing

    View Slide

  79. type Maybe a
    = Just a
    | Nothing
    Wraps the
    successful value

    View Slide

  80. type Maybe a
    = Just a
    | Nothing Represents no result
    or missing value

    View Slide

  81. type Maybe a
    = Just a
    | Nothing
    Type Variable

    View Slide

  82. type Maybe a
    = Just a
    | Nothing
    Either I have Just the value a,
    or I have Nothing.

    View Slide

  83. divide : Float -> Float -> Maybe Float
    divide x y =
    if y == 0 then
    Nothing
    else
    Just (x / y)
    divide 4 2 -- Just 2
    divide 4 0 -- Nothing

    View Slide

  84. divide : Float -> Float -> Maybe Float
    divide x y =
    if y == 0 then
    Nothing
    else
    Just (x / y)
    divide 4 2 -- Just 2
    divide 4 0 -- Nothing

    View Slide

  85. divide : Float -> Float -> Maybe Float
    divide x y =
    if y == 0 then
    Nothing
    else
    Just (x / y)
    divide 4 2 -- Just 2
    divide 4 0 -- Nothing

    View Slide

  86. divide : Float -> Float -> Maybe Float
    divide x y =
    if y == 0 then
    Nothing
    else
    Just (x / y)
    divide 4 2 -- Just 2
    divide 4 0 -- Nothing

    View Slide

  87. divide : Float -> Float -> Maybe Float
    divide x y =
    if y == 0 then
    Nothing
    else
    Just (x / y)
    divide 4 2 -- Just 2
    divide 4 0 -- Nothing

    View Slide

  88. divide : Float -> Float -> Maybe Float
    divide x y =
    if y == 0 then
    Nothing
    else
    Just (x / y)
    divide 4 2 -- Just 2
    divide 4 0 -- Nothing

    View Slide

  89. case divide 4 2 of
    Just n ->
    "Result is " ++ (toString n)
    Nothing ->
    "No Result"

    View Slide

  90. case divide 4 2 of
    Just n ->
    "Result is " ++ (toString n)
    Nothing ->
    "No Result"

    View Slide

  91. case divide 4 2 of
    Just n ->
    "Result is " ++ (toString n)
    Nothing ->
    "No Result"

    View Slide

  92. case divide 4 2 of
    Just n ->
    "Result is " ++ (toString n)
    Nothing ->
    "No Result"

    View Slide

  93. case divide 4 2 of
    Just n ->
    "Result is " ++ (toString n)
    -- Nothing ->
    -- "No Result"

    View Slide

  94. Exhaustive matching
    This `case` does not have branches for all possibilities.
    21|> case divide 4 2 of
    22|> Just n ->
    23|> "Result is " ++ (toString n)
    You need to account for the following values:
    Maybe.Nothing
    Add a branch to cover this pattern!

    View Slide

  95. Update
    View
    Model
    Messages
    The Elm
    Architecture

    View Slide

  96. Demos
    The Elm Architecture in Action

    View Slide

  97. Getting
    Started
    • elm-lang.org
    • elm-lang.org/examples
    • guide.elm-lang.org
    • www.elm-tutorial.org
    • builtwithelm.co
    • Slack
    • elmlang.herokuapp.com

    View Slide

  98. Say [email protected]
    Thank you!
    Jeremy Fairbank / @elpapapollo

    View Slide