Slide 1

Slide 1 text

Ch-ch-ch-ch-changes in Elm 0.17.0

Slide 2

Slide 2 text

Agenda Changelog, Walthrough

Slide 3

Slide 3 text

Brian Hicks Asteris

Slide 4

Slide 4 text

September 15, 2016 / elm-conf.us

Slide 5

Slide 5 text

Changes

Slide 6

Slide 6 text

Package Moves · evancz/elm-html -> elm-lang/html · evancz/elm-svg -> elm-lang/svg · evancz/elm-effects -> elm-lang/ core · evancz/start-app -> Html.App

Slide 7

Slide 7 text

Action is now Msg -- 0.16 type Action = Increment | Decrement -- 0.17 type Msg = Increment | Decrement

Slide 8

Slide 8 text

Header Changes -- 0.16 module X where -- 0.17 module X exposing (..)

Slide 9

Slide 9 text

Core Moves · Signal -> ! · Effects -> ! (the functionality's still there, but the modules aren't)

Slide 10

Slide 10 text

What about Signal.Address? 0.16: view : Signal.Address Action -> Model -> Html view address model = div [] [ button [ onClick address Decrement ] [ text "-" ] , div [ countStyle ] [ text (toString model) ] , button [ onClick address Increment ] [ text "+" ] ]

Slide 11

Slide 11 text

What about Signal.Address? 0.17: view : Model -> Html Msg view model = div [] [ button [ onClick Decrement ] [ text "-" ] , div [ countStyle ] [ text (toString model) ] , button [ onClick Increment ] [ text "+" ] ]

Slide 12

Slide 12 text

What about Signal.Address? App.map: -- Child.elm type Msg = SomeEvent view : Model -> Html Msg view model = model |> toString |> Html.text -- Parent.elm type Msg = ChildMsg Child.Msg | ... view : Model -> Html Msg view model = map ChildMsg <| Child.view model.child

Slide 13

Slide 13 text

What about Signal.Address? Avoiding App.map: -- Child.elm view : Model -> Html a view model = model |> toString |> Html.text -- Parent.elm type Msg = ChildMsg Child.Msg | ... view : Model -> Html Msg view model = Child.view model.child

Slide 14

Slide 14 text

And Effects? 0.16: update : Action -> Model -> (Model, Effects Action) update action model = case action of RequestMore -> ( model, getRandomGif model.topic ) NewGif maybeUrl -> ( Model model.topic (Maybe.withDefault model.gifUrl maybeUrl) , Effects.none )

Slide 15

Slide 15 text

And Effects? 0.17: update : Msg -> Model -> (Model, Cmd Msg) update msg model = case msg of RequestMore -> ( model, getRandomGif model.topic ) NewGif maybeUrl -> ( Model model.topic (Maybe.withDefault model.gifUrl maybeUrl) , Cmd.none )

Slide 16

Slide 16 text

And Effects? 0.17: update : Msg -> Model -> (Model, Cmd Msg) update msg model = case msg of RequestMore -> ( model, getRandomGif model.topic ) NewGif maybeUrl -> Model model.topic (Maybe.withDefault model.gifUrl maybeUrl) ! [ ]

Slide 17

Slide 17 text

And Effects? What's this ! do? (!) : model -> List (Cmd msg) -> (model, Cmd msg) (!) model commands = (model, Msg.batch commands) -- so this is true: ( model, Cmd.none ) == model ! [ ]

Slide 18

Slide 18 text

StartApp is now Html.App 0.16: import StartApp import Task app = StartApp.start { init = init, update = update, view = view, inputs = [] } main = app.html port tasks : Signal (Task.Task Never ()) port tasks = app.tasks

Slide 19

Slide 19 text

StartApp is now Html.App 0.17: import Html.App as Html main = Html.program { init = init , update = update , view = view , subscriptions = \_ -> Sub.none }

Slide 20

Slide 20 text

Ports (Outgoing) -- 0.16 port focus : Signal String port focus = ... -- 0.17 port focus : String -> Cmd msg

Slide 21

Slide 21 text

Ports (Incoming) type User = { name : String, age : Int } -- 0.16 port users : Signal User -- 0.17 port users : (User -> msg) -> Sub msg

Slide 22

Slide 22 text

Embedding // 0.16 Elm.embed(Elm.Main, someNode); Elm.fullscreen(Elm.Main); // 0.17 Elm.Main.embed(someNode); Elm.Main.fullscreen();

Slide 23

Slide 23 text

Navigation · elm-history -> elm-lang/navigation · wraps the new Html.App program · takes an additional argument for updating navigation state

Slide 24

Slide 24 text

Navigation -- your nav type yourParserFunc : Navigation.Location -> List String yourParserFunc loc = loc.hash |> split "/" |> List.filter (\seg -> seg /= "" && seg /= "#") main = Navigation.program (Navigation.makeParser yourParserFunc) { init = init , update = update -- Msg -> Model -> ( Model, Cmd Msg ) , urlUpdate = urlUpdate -- List String -> Model -> ( Model, Cmd Msg ) , view = view , subscriptions = subscriptions }

Slide 25

Slide 25 text

Navigation evancz/url-parser blog : Parser (Int -> String -> a) a blog = s "blog" > int > string The parser gets /blog/42/whale-songs and returns (42, "whale-songs")

Slide 26

Slide 26 text

My Migration

Slide 27

Slide 27 text

Plan · update packages · fix module headers · renames like Action -> Msg · remove usage of Signal and Effects · remove StartApp fork for Html.App · run elm-format on everything

Slide 28

Slide 28 text

Reality You can't do these things one at a time. Plan for it to be messy.

Slide 29

Slide 29 text

Outcome · PR: +1,077 -867 · No user-facing changes ! · Output JS: 354K to 244K

Slide 30

Slide 30 text

Thank You! @brianhicks brian@brianthicks.com