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

Elmのさわれる副作用

 Elmのさわれる副作用

M3 tech meetup! #2 ~フロントエンドの副作用~ にて
http://m3-engineer.connpass.com/event/33802/

Yosuke Torii

July 14, 2016
Tweet

More Decks by Yosuke Torii

Other Decks in Technology

Transcript

  1. Elm のさわれる副作用
    2016/07/14
    Yosuke Torii

    View Slide

  2. ・鳥居 陽介
    ・株式会社ワークスアプリケーションズ勤務
    ・ CodeZine に 6 記事 (React.js, HTTP/2, Elm, BLE)
    ・ジンジャー研究室
    誰?
    @jinjor

    View Slide

  3. Elm の紹介

    View Slide

  4. main =
    span [class "message"] [text "Hello, World!"]
    ・関数型言語
    ・静的型付き言語
    ・ JavaScript にコンパイルされる
    ・ 2012 年誕生
    Elm is 何?

    View Slide

  5. Elm = 言語 + フレームワーク
    ・ Virtual DOM 採用
    ・ Redux を生み出すきっかけになった
     「 Elm Architecture 」
    ・ http://guide.elm-lang.org/

    View Slide

  6. Elm = 言語 + フレームワーク
    ・ Virtual DOM 採用
    ・ Redux を生み出すきっかけになった
     「 Elm Architecture 」
    ・ http://guide.elm-lang.org/
    React.js/Flux を追っている人なら
    Elm を楽しめるはず!

    View Slide

  7. 副作用の話

    View Slide

  8. Elm は副作用を
    厳密に扱う言語

    View Slide

  9. 関数型言語としての位置づけ
    JavaScript
    Ruby
    Python TypeScript
    Java Scala Haskell
    Elm
    F#
    OCaml
    C#
    型の強さ
    Flow

    View Slide

  10. 関数型言語としての位置づけ
    JavaScript
    Ruby
    Python TypeScript
    Java Scala Haskell
    Elm
    F#
    OCaml
    C#
    型の強さ
    Flow

    View Slide

  11. 関数型言語としての位置づけ
    JavaScript
    Ruby
    Python TypeScript
    Java Scala Haskell
    Elm
    F#
    OCaml
    C#
    副作用を
    厳密に
    を扱う
    Flow

    View Slide

  12. どういうことか

    View Slide

  13. Flow で型をつけてみる
    function add(a, b) {
    return a + b;
    }

    View Slide

  14. add() は number を返す関数
    function add(a, b): number {
    return a + b;
    }

    View Slide

  15. add() は number を返す関数
    function add(a, b): number {
    callCount++;
    return a + b;
    }

    View Slide

  16. add() は number を返す関数
    function add(a, b): number {
    callCount++;
    sendLogToServer('Hey');
    return a + b;
    }

    View Slide

  17. add() は number を返す関数
    function add(a, b): number {
    callCount++;
    sendLogToServer('Hey');
    clearLocalStorage();
    return a + b;
    }

    View Slide

  18. add() は number を返す関数
    function add(a, b): number {
    callCount++;
    sendLogToServer('Hey');
    clearLocalStorage();
    fireMissiles();
    return a + b;
    }

    View Slide

  19. 関数の型情報から
    副作用の有無は分からない

    View Slide

  20. もう少し現実的な例
    function submit(state): State {
    send(state.inputField);
    return Object.assign({}, state, {
    disableSend: true,
    inputField: “”
    });
    }

    View Slide

  21. Elm で副作用を扱う方法
    submit : State -> (State, Cmd Msg)
    submit state =
    ( { state |
    inputField = “”
    , disableSend = True
    }
    , send state.inputField
    )

    View Slide

  22. Elm で副作用を扱う方法
    submit : State -> (State, Cmd Msg)
    submit state =
    ( { state |
    inputField = “”
    , disableSend = True
    }
    , send state.inputField
    )

    View Slide

  23. 型に書いていないことをすると…
    submit : State -> State
    submit state =
    ( { state |
    inputField = “”
    , disableSend = True
    }
    , send state.inputField
    )

    View Slide

  24. -- TYPE MISMATCH -----------------------------------------------
    The type annotation for `update` does not match its definition.
    50| update : Msg -> Model -> Model
    ^^^^^^^^^^^^^^^^^^^^^
    The type annotation is saying:
    Msg -> Model -> { disableSend : Bool, inputField : String }
    But I am inferring that the definition has this type:
    Msg -> Model -> ( Model, Cmd a )

    View Slide

  25. あえて返さないでみる
    submit : State -> State
    submit model =
    let
    unused = send model.inputField
    in
    { model |
    inputField = “”
    , disableSend = True
    }

    View Slide

  26. しかし なにも おこらなかった!

    View Slide

  27. Cmd そのものは副作用ではない
    Elm ランタイムに
    Cmd を返すと
    副作用を起こせる
    Cmd Msg
    update : Msg
    → Model
    → (Model, Cmd Msg)

    View Slide

  28. おいしいところ

    View Slide

  29. 1.副作用の発見

    View Slide

  30. 副作用を起こす関数はどれ?
    parse(s: string): AST
    format(s: string): string
    update(model: Model, action: Action): Model
    register(model: Model, user: User): Model
    makeURL(model: Model): string

    View Slide

  31. parse : String → AST
    format : String → String
    update : Model → Action → Model
    register : Model → User → Model
    makeURL : Model → (String, Cmd Msg)
    副作用を起こす関数はどれ?

    View Slide

  32. 2.副作用の禁止・許可

    View Slide

  33. 設計上、副作用を禁止したい
    var newState =
    reduce(oldState, action);

    View Slide

  34. 設計上、副作用を禁止したい
    http://redux.js.org/docs/basics/Reducers.html
    ”Given the same arguments, it should
    calculate the next state and return it. No
    surprises. No side effects. No API calls. No
    mutations. Just a calculation.”
    var newState =
    reduce(oldState, action);

    View Slide

  35. しかし、保証はできない
    var newState =
    reduce(oldState, action);
    ”Given the same arguments, it should
    calculate the next state and return it. No
    surprises. No side effects. No API calls. No
    mutations. Just a calculation.”
    http://redux.js.org/docs/basics/Reducers.html

    View Slide

  36. Elm なら型で拘束できる
    update :
    Msg → Model → (Model, Cmd Msg)
    view : Model → Html Msg
    update 関数では副作用を起こせる
    view 関数では絶対に副作用を起こせない

    View Slide

  37. まとめ

    View Slide

  38. 副作用を可視化すると
    メリットが沢山ある!

    View Slide

  39. Elm で快適 Frontend Life
    を満喫しよう

    View Slide

  40. ありがとうございました

    View Slide