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

純粋関数型言語では副作用をどう扱うのか / Side Effects in Purely Functional Languages

tipo159
June 06, 2017

純粋関数型言語では副作用をどう扱うのか / Side Effects in Purely Functional Languages

純粋関数型言語での副作用の扱い方としてStream-based I/OとMonadic I/Oを、純粋関数型AltJS(PureScriptとElm)での副作用の扱い方を紹介しています。
We Are JavaScripters! 8th
WeJS

tipo159

June 06, 2017
Tweet

More Decks by tipo159

Other Decks in Programming

Transcript

  1. 純粋関数型言語では
    副作用をどう扱うのか
    We Are JavaScripters! 8th
    2017/6/6

    View full-size slide

  2. 自己紹介
    ▰ 仕事ではC++, Java等でインフラ開発
    ▰ JavaScriptはHackathonへ参加するために
    勉強中
    ▰ 以前Alfa Romeo 156に乗っていたので、こ
    の名前を使用
    2
    河原崎(@tipo159)

    View full-size slide

  3. アウトライン
    1. 純粋関数型言語での副作用の扱い方
    ▻ Stream-based I/O
    ▻ Monadic I/O
    2. 純粋関数型AltJSでの副作用の扱い方
    ▻ PureScript
    ▻ Elm
    3. まとめ
    3

    View full-size slide

  4. 純粋関数型言語での副作用の
    扱い方
    4
    1

    View full-size slide

  5. 5
    純粋関数型言語
    は副作用のある
    関数を使えない
    副作用がないと
    実用的なプログ
    ラムは書けない
    問題点

    View full-size slide

  6. 6
    Haskellプログラム
    [Response] [Request]
    Stream-based I/Oの概念図 (Haskell 1.0)
    main :: [Response] -> [Request]
    副作用をプログラムの入出力として扱う

    View full-size slide

  7. main :: [Response] -> [Request]
    data Request = ReadFile Name
    | WriteFile Name String
    | …
    data Response = Success
    | Str String
    | Failure IOError
    | …
    Stream-based I/Oの定義抜粋
    7

    View full-size slide

  8. main :: Dialogue
    main ~(Success : ~((Str userInput) : ~(Success : ~(r4 : _))))
    = [ AppendChan stdout "please type a filename\n",
    ReadChan stdin,
    AppendChan stdout name,
    ReadFile name,
    AppendChan stdout (case r4 of Str contents -> contents
    Failure ioerr -> "can’t open file")
    ] where (name : _) = lines userInput
    Stream-based I/Oのプログラム例
    8
    Requests:
    [AppendChan …, ReadChan …, AppendChan …, ReadFile …, AppendChan …]
    Response:
    [Success, Str userInput, Success, Str contents or Failure ioerr, Success]

    View full-size slide

  9. Stream-based I/Oの問題点
    ▰ 拡張が困難: 新しいI/O操作を追加するためには
    言語仕様の変更が必要
    ▰ RequestとResponseの対応付けが困難: Haskellは
    遅延評価のため、評価順序の遅延パターンによ
    る記述が必要
    ▰ 二つのmainプログラムの合成が不可能
    9

    View full-size slide

  10. 10
    IO t
    Monadic I/Oの概念図 (Haskell 98)
    main:: IO ()
    type IO t = World -> (t, World)
    result :: t
    タイプ(IO t)の値は、Action
    実行されるとタイプtの結果を返す前にIOを行う

    View full-size slide

  11. 11
    Actionはファーストクラスオブジェクト
    type IO t = World -> (t, World)
    ▰ Actionはファーストクラスオブジェクト
    ▻ 複数Actionの合成が可能
    ▰ Actionの評価(Evaluating)は作用なし
    ▻ 遅延評価等の評価順序とは違う概念
    ▰ Actionの実行(Performing)は作用あり

    View full-size slide

  12. 12
    Action合成の例
    putChar
    getChar
    Char ()
    getChar :: IO Char
    putChar :: Char -> IO ()
    getCharとputCharを合成

    View full-size slide

  13. 13
    Bindコンビネータ(>>=) [1 / 3]
    putChar
    getChar
    Char ()
    (>>=) :: IO a -> (a -> IO b) -> IO b
    echo :: IO ()
    Echo = getChar >> = putChar

    View full-size slide

  14. 14
    Bindコンビネータ(>>=) [2 / 3]
    ▰ bindコンビネータは左側のActionの結果を右側
    のActionとbindする

    View full-size slide

  15. 15
    Bindコンビネータ(>>=) [3 / 3]
    ▰ 合成Action a >>= \x -> bを実行すると
    ▻ aを実行して結果rを提供(yield)
    ▻ 関数\x -> bをrに適用(apply)
    ▻ b{x <- r}の結果Actionを実行
    ▻ 結果vを返却
    b
    a
    r v
    x

    View full-size slide

  16. Stream-based I/Oの問題点を解決
    ▰ 拡張が困難: ライブラリとして新しいモナドを追加可

    ▰ RequestとResponseの対応付けが困難: bindコンビ
    ネータで、左側を先に評価することを保証
    ▰ 二つのmainプログラムの合成が不可能: bindコン
    ビネータで合成が可能
    16

    View full-size slide

  17. 純粋関数型AltJSでの副作用の
    扱い方
    17
    2

    View full-size slide

  18. 18
    PureScript
    Monadic I/Oを採用
    HaskellのMonadと違い、副作用の対象を明記
    main:: forall e. Eff (fs :: FS, console:: CONSOLE | e) Unit
    この例ではmainはファイルシステムを使用し、
    コンソールにメッセージを出力する

    View full-size slide

  19. 19
    Elm
    The Elm Architectureに基づき、副作用はElm Runtimeで実施
    ▰ The Elm ArchitectureはWebフレームワークの様なもの
    ▰ アプリケーションの状態をModelで、Modelの更新方法を
    Updateで、モデルの表示をViewで定義する
    ▰ Stream-based I/OのRequestに対応するCmdと、Responseに
    対応するSubで副作用のある処理を管理

    View full-size slide

  20. 20
    ElmのCmd/Subの概念図
    Elm Runtime
    update
    Msg
    Html Cmd Sub
    Subで購読を指定したMsgがElm Runtimeから通知される

    View full-size slide

  21. Stream-based I/Oの問題点は大丈夫?
    対象をフロントエンドに限定しているため問題ない
    ▰ 拡張が困難: 新しいI/O操作を追加する時にはThe
    Elm Architectureの変更が必要になるため問題ない
    ▰ RequestとResponseの対応付けが困難: 遅延評価で
    はないため問題ない
    ▰ 二つのmainプログラムの合成が不可能: mainプログ
    ラムの合成はできなくても問題ない 21

    View full-size slide

  22. まとめ
    22
    3

    View full-size slide

  23. 23
    まとめ
    ▰ 純粋関数型言語
    ▻ Stream-based I/O: 副作用をプログラムの入出力に
    ▻ Monadic I/O: Actionが値となるモナドを使用
    ▰ 純粋関数型AltJS
    ▻ PureScript: モナドを使用
    ▻ Elm: Stream-based I/Oに類似したCmd/Subを使用

    View full-size slide