Elmで始めるFunctional Reactive Programming
-
Upload
yasuyuki-maeda -
Category
Technology
-
view
7.444 -
download
0
description
Transcript of Elmで始めるFunctional Reactive Programming
フロントエンドに忍び寄る関数型の影
Elmで始める Functional Reactive Programming
前田康行 (@maeda_) 2013/2/23 大なごやjs
自己紹介
! 前田康行 ( @maeda_ )
! 名古屋在住のフリーランス(http://www.illi-ichi.com)
! 好きな言語 ! Scala ! Smalltalk
! DyNagoya (http://dynagoya.info/) = Dynamic language + Nagoya
この資料の目的
! 想定対象者 ! 普段はJavascriptなど、型のない言語を使っている
! 最近、関数型が流行っているらしいとは聞くが実態は知らない
! または、関数型言語の勉強をしてみたが、実践的なアプリケーションの作り方は分からない
! そういった人たちに、関数型プログラミングの イメージを伝えることが目的です。
! 知らない用語が出てきても、スルーすれば大丈夫なはず。
Elmについて
Elm とは
! Elm (http://elm-lang.org)
! FRP(Functional Reactive Programming)をベースとしたWebアプリケーションフレームワーク
! Elmのコード → Javascript + HTML + CSS を生成
! HaskellをベースにWebアプリに適した文法を独自定義 ! Native Markdown support
! Extensible Records
本家ページ(http://elm-lang.org)
! このページもElmで作られている
本家ページ(http://elm-lang.org) ! サンプルが豊富
! ブラウザ上でコードを試せる
! 画面左のコードはサーバー側でコンパイルされて、生成物が右側に表示される
Functional Reactive Programming
Reactive Programmingとは
! 典型例:Excel
! A1やB1のセルの値を変えると、C1の値も勝手に変わる
! C1の中で、A1やB1はReactiveな値
もし、Javascriptで書いたら・・・ ! セルの状態を管理したり
! 更新時のcallbackを設定したり
const sum = function(outCell){ var x, y; function update(){ sheet(outCell).value(x + y); } return { updateX: function(cell) { x = cell.value(); update() }, updateY: function(cell) { y = cell.value(); update() } }; }("C1"); sheet("A1").on("update", sum.updateX); sheet("B1").on("update", sum.updateY);
※これは架空のコードです。
もし、Elmで書いたら・・・
! このコードで、A1,B1の値が更新されたら、C1の値が更新される
main = lift (Excel.update "C1") $ (+) <〜 Excel.cell "A1" 〜 Excel.cell "B1"
※これは架空のコードです。
ブラウザ上でもReactiveがいい ! マルチタッチ対応のお絵描きアプリも5行で
(本家ページのBasic – Touch – Drawのサンプル)
add t d = let vs = Dict.findWithDefault [] t.id d in Dict.insert t.id ((t.x,t.y):vs) d scene (w,h) = collage w h . map (solid red . line) main = let ts = foldp ( \ts d -> foldl add d ts) Dict.empty Touch.touches in lift2 scene Window.dimensions (lift Dict.values ts)
※これは架空のコードではありません。
3本指で同時に描いた線 →
Callback地獄からの脱却
! シングルスレッドなJSでは、コールバックが多用される
! 一般的に、Callbackはコードの流れを断絶し、可読性を下げることが多い
! ElmならReactiveで、かつ、Functionalなコードが書ける
Functionalな プログラミング
Functionalなプログラミング とは 1. (ただの)Functional Programming 関数を組み合わせてプログラムを構成
2. Purely Functional Programming 純粋な関数(副作用がない関数)でプログラムを構成 (= 外界に影響を与えず、同じ引数には同じ戻り値を返す) ! 副作用の例
! マウスの位置やクリック状況を取得 ! 画面に何かを描画する ! Ajax通信 ! 時間を取得 ! 変数の値(状態)を書き換える
Elmは純粋な関数しか作れない!
純粋な関数
副作用のないプログラミング 「外部から副作用をもらった時、どう副作用を与えるか」を記述する。
Key Down
Reactiveな値 (ライブラリとして提供)
Timer
画面表示
実行時に変化があると、 値を純粋な関数に流し込む
純粋な関数
副作用のないプログラミング 「外部から副作用をもらった時、どう副作用を与えるか」を記述する。
Key Down
Timer
画面表示
f1
f2
f3
f4
純粋な関数を合成して ひとつの関数を作る
外部の値をもらう時は 普通の適用とは異なる
「意味イベント」を作る ! 意味イベントという言葉はITプランニング小笠原さんが発案
http://www.itpl.co.jp/tech/func/event-driven.pdf
! 生のイベントを変換/合成して、より意味のあるイベントにする
純粋な関数
Key Down
Timer
画面表示
ダイアログを閉じる
ESCキーを 押下
Mouse Click ×ボタンをクリック
一定時間 経過
ElmでProgramming
Elmは強い型付け言語 ! 値には必ず型がつく。
! Int, String, Float, ...
! [a](リスト), Set a(集合), Dict a(ハッシュテーブル)
! 関数(A → B → C はA型とB型を受け取って、C型を返す関数)
! 代数データ型、レコード
! 関数に渡すときに、型が合わないとコンパイルエラー
f1 :: Float →Int f2 :: Int→String 3.5 :: Float “□□□” :: String
※「a :: A」という表記はaがA型であることを
「A→B」という表記はA型からB型に変換する関数を示す
型チェック 型チェック
Reactiveな世界 純粋な世界
Signal a型 (aは何かの型)
! 純粋な値と外部からやってくる値を型で区別
! 外からやってくるReactiveな値は「Signal a型」となる (aには純粋な世界の型が入る)
! 「Signal Int型」は何らかの数値(Int)の値となるReactiveな値を表す
Int
String
Element
Time Signal Int
Signal String
Signal Element
Signal Time
Reactiveな値を変換する ! Reactiveな値を変換する場合、関数をReactiveな世界に持ち上げて(liftして)、適用する
Reactiveな世界 純粋な世界
format :: Int → String
Mouse.x :: Signal Int 30 :: Int
"X座標は30です" :: String "X座標は□です" :: Signal String
lift format :: Signal Int → Signal String
Signal Element型に持っていく ! 画面に表示されるものはElement型で表される
! Signal a型の値を変換して、 最終的にSignal Element型を作るようなmain関数を作る
-- マウスカーソルに合わせて画像をリサイズする drawImage (w, h) = image w h "/images/hoge.jpg" main = lift drawImage Mouse.position
drawImage :: (Int, Int) → Element
lift drawImage :: Signal (Int, Int) → Signal Element
Mouse.position :: Signal (Int, Int)
main :: Signal Element
最後に
関数型言語の教材として Elmはよいのではないか?
! お手軽 ! ブラウザ上で、目に見える形で動作するアプリケーションがすぐに試せる
! 簡単 ! 出来る事が限定されているのでHaskellよりも簡単 ! 簡単側に倒れていることが多い
! IO Monadがない。Functorが分かれば大丈夫 ! ただしSignalのダイナミックな配線の変更はできない
! 教育的 ! サンプルが豊富
! サンプルのコメントにExerciseがあったり ! ピンポンゲームの作成チュートリアルもある ! 標準ライブラリが弱いので、自分で定義しなくてはならない
一方で、Elmの注意点 ! まだ発展途上。いろいろ厳しい
! コンパイルエラーが分かりにくい ! 修行だと思ってください
! REPLがない ! 型を調べたり、ちょっとした確認が面倒
! ブラウザ上でHaskellを動かしたいわけではない。 ! Haskellをベースにブラウザ+FRPに適した構文を追求
! Haskellは遅延評価だが、Elmは正格評価 遅延評価でFRPを実装するのは難しいらしい (メモリリークなどの観点で)
! where句は実装予定 ! 特殊なifの構文
Elmを始めるには
! まずHaskellの勉強から ! 「すごいHaskell楽しく学ぼう(通称:すごいH本)」
11章あたりまで読めれば十分。途中まででも多分大丈夫
! Haskellの基本は分かったがアプリを作るイメージが湧かない → そこでElmをやってみる ! サンプルを適当にいじってみたり
! ピンポンのチュートリアルやったり
(おまけ) 説明しきれなかったこと
! 状態を扱いたい → foldpを使う
foldp :: (a → b → b) → b → Signal a → Signal b
! Javascriptとの連携(FFI) ! JS側で登録したイベントをSignal aとしてElmで扱う
! ElmのSignal aをイベントとしてJS側に渡す
! Applicativeスタイルでの記述 (<〜) :: (a → b) → Signal a → Signal b
(〜) :: Signal (a → b) → Signal a → Signal b
(おまけ) elm-serverをローカルで立てる
! Mac OS X で home brew を使用した場合
> brew install ghc > brew install cabal-install > cd (git repos) > git clone https://github.com/evancz/Elm.git > cd Elm/elm > cabal install Elm.cabal > cd (git repos) > git clone https://github.com/evancz/elm-lang.org.git > cd elm-lang.org/ > ./compile.sh > ./server/Server ブラウザでhttp://localhost:8000/ を開く
参考文献
! Elm: Concurrent FRP for Functional GUIs http://www.testblogpleaseignore.com/wp-content/uploads/2012/04/thesis.pdf
Elmの論文
! イベントドリブンプログラミングの関数型的書き方 http://www.itpl.co.jp/tech/func/event-driven.pdf
FRPという言葉のないFRPの説明(OCaml)
! maoeのブログ「FRPの話」 http://maoe.hatenadiary.jp/entry/2012/12/24/011414
包括的なFRPのまとめ(ほぼHaskell) ちなみにElmはArrowized FRP