Elmで始めるFunctional Reactive Programming

30
フロントエンドに忍び寄る関数型の影 Elmで始める Functional Reactive Programming 前田康行 (@maeda_) 2013/2/23 大なごやjs

description

ElmはHaskellと同じく純粋関数型言語のひとつで、ブラウザ上で動くアプリケーションの作成に特化しています。目に見えるものがすぐに作れるなど、関数型プログラミングやFRP(Functional Reactive Programming)の入門によい面がいくつかあります。JavaScriptなど型のない手続き型言語に慣れた人向けに関数型プログラミングのイメージを掴んでもらうことを目的にしています。

Transcript of Elmで始めるFunctional Reactive Programming

Page 1: Elmで始めるFunctional Reactive Programming

フロントエンドに忍び寄る関数型の影

Elmで始める Functional Reactive Programming

前田康行 (@maeda_) 2013/2/23 大なごやjs

Page 2: Elmで始めるFunctional Reactive Programming

自己紹介

!   前田康行 ( @maeda_ )

!   名古屋在住のフリーランス(http://www.illi-ichi.com)

!   好きな言語 ! Scala !   Smalltalk

! DyNagoya (http://dynagoya.info/) = Dynamic language + Nagoya

Page 3: Elmで始めるFunctional Reactive Programming

この資料の目的

!   想定対象者 !   普段はJavascriptなど、型のない言語を使っている

!   最近、関数型が流行っているらしいとは聞くが実態は知らない

!   または、関数型言語の勉強をしてみたが、実践的なアプリケーションの作り方は分からない

!   そういった人たちに、関数型プログラミングの イメージを伝えることが目的です。

!   知らない用語が出てきても、スルーすれば大丈夫なはず。

Page 4: Elmで始めるFunctional Reactive Programming

Elmについて

Page 5: Elmで始めるFunctional Reactive Programming

Elm とは

!   Elm (http://elm-lang.org)

!   FRP(Functional Reactive Programming)をベースとしたWebアプリケーションフレームワーク

!   Elmのコード → Javascript + HTML + CSS を生成

!   HaskellをベースにWebアプリに適した文法を独自定義 !   Native Markdown support

!   Extensible Records

Page 6: Elmで始めるFunctional Reactive Programming

本家ページ(http://elm-lang.org)

!   このページもElmで作られている

Page 7: Elmで始めるFunctional Reactive Programming

本家ページ(http://elm-lang.org) !   サンプルが豊富

!   ブラウザ上でコードを試せる

!   画面左のコードはサーバー側でコンパイルされて、生成物が右側に表示される

Page 8: Elmで始めるFunctional Reactive Programming

Functional Reactive Programming

Page 9: Elmで始めるFunctional Reactive Programming

Reactive Programmingとは

!   典型例:Excel

!   A1やB1のセルの値を変えると、C1の値も勝手に変わる

!   C1の中で、A1やB1はReactiveな値

Page 10: Elmで始めるFunctional Reactive Programming

もし、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);

※これは架空のコードです。

Page 11: Elmで始めるFunctional Reactive Programming

もし、Elmで書いたら・・・

!   このコードで、A1,B1の値が更新されたら、C1の値が更新される

main = lift (Excel.update "C1") $ (+) <〜 Excel.cell "A1" 〜 Excel.cell "B1"

※これは架空のコードです。

Page 12: Elmで始めるFunctional Reactive Programming

ブラウザ上でも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本指で同時に描いた線 →

Page 13: Elmで始めるFunctional Reactive Programming

Callback地獄からの脱却

!   シングルスレッドなJSでは、コールバックが多用される

!   一般的に、Callbackはコードの流れを断絶し、可読性を下げることが多い

!   ElmならReactiveで、かつ、Functionalなコードが書ける

Page 14: Elmで始めるFunctional Reactive Programming

Functionalな プログラミング

Page 15: Elmで始めるFunctional Reactive Programming

Functionalなプログラミング とは 1.  (ただの)Functional Programming 関数を組み合わせてプログラムを構成

2.  Purely Functional Programming 純粋な関数(副作用がない関数)でプログラムを構成 (= 外界に影響を与えず、同じ引数には同じ戻り値を返す) !   副作用の例

!   マウスの位置やクリック状況を取得 !   画面に何かを描画する !   Ajax通信 !   時間を取得 !   変数の値(状態)を書き換える

Elmは純粋な関数しか作れない!

Page 16: Elmで始めるFunctional Reactive Programming

純粋な関数

副作用のないプログラミング 「外部から副作用をもらった時、どう副作用を与えるか」を記述する。

Key Down

Reactiveな値 (ライブラリとして提供)

Timer

画面表示

実行時に変化があると、 値を純粋な関数に流し込む

Page 17: Elmで始めるFunctional Reactive Programming

純粋な関数

副作用のないプログラミング 「外部から副作用をもらった時、どう副作用を与えるか」を記述する。

Key Down

Timer

画面表示

f1

f2

f3

f4

純粋な関数を合成して ひとつの関数を作る

外部の値をもらう時は 普通の適用とは異なる

Page 18: Elmで始めるFunctional Reactive Programming

「意味イベント」を作る !   意味イベントという言葉はITプランニング小笠原さんが発案

http://www.itpl.co.jp/tech/func/event-driven.pdf

!   生のイベントを変換/合成して、より意味のあるイベントにする

純粋な関数

Key Down

Timer

画面表示

ダイアログを閉じる

ESCキーを 押下

Mouse Click ×ボタンをクリック

一定時間 経過

Page 19: Elmで始めるFunctional Reactive Programming

ElmでProgramming

Page 20: Elmで始めるFunctional Reactive 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型に変換する関数を示す

型チェック 型チェック

Page 21: Elmで始めるFunctional Reactive Programming

Reactiveな世界 純粋な世界

Signal a型 (aは何かの型)

!   純粋な値と外部からやってくる値を型で区別

!   外からやってくるReactiveな値は「Signal a型」となる (aには純粋な世界の型が入る)

!   「Signal Int型」は何らかの数値(Int)の値となるReactiveな値を表す

Int

String

Element

Time Signal Int

Signal String

Signal Element

Signal Time

Page 22: Elmで始めるFunctional Reactive Programming

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

Page 23: Elmで始めるFunctional Reactive Programming

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

Page 24: Elmで始めるFunctional Reactive Programming

最後に

Page 25: Elmで始めるFunctional Reactive Programming

関数型言語の教材として Elmはよいのではないか?

!   お手軽 !   ブラウザ上で、目に見える形で動作するアプリケーションがすぐに試せる

!   簡単 !   出来る事が限定されているのでHaskellよりも簡単 !   簡単側に倒れていることが多い

!   IO Monadがない。Functorが分かれば大丈夫 !   ただしSignalのダイナミックな配線の変更はできない

!   教育的 !   サンプルが豊富

!   サンプルのコメントにExerciseがあったり !   ピンポンゲームの作成チュートリアルもある !   標準ライブラリが弱いので、自分で定義しなくてはならない

Page 26: Elmで始めるFunctional Reactive Programming

一方で、Elmの注意点 !   まだ発展途上。いろいろ厳しい

!   コンパイルエラーが分かりにくい !   修行だと思ってください

!   REPLがない !   型を調べたり、ちょっとした確認が面倒

!   ブラウザ上でHaskellを動かしたいわけではない。 !   Haskellをベースにブラウザ+FRPに適した構文を追求

!   Haskellは遅延評価だが、Elmは正格評価 遅延評価でFRPを実装するのは難しいらしい (メモリリークなどの観点で)

!   where句は実装予定 !   特殊なifの構文

Page 27: Elmで始めるFunctional Reactive Programming

Elmを始めるには

!   まずHaskellの勉強から !   「すごいHaskell楽しく学ぼう(通称:すごいH本)」

11章あたりまで読めれば十分。途中まででも多分大丈夫

!   Haskellの基本は分かったがアプリを作るイメージが湧かない → そこでElmをやってみる !   サンプルを適当にいじってみたり

!   ピンポンのチュートリアルやったり

Page 28: Elmで始めるFunctional Reactive Programming

(おまけ) 説明しきれなかったこと

!   状態を扱いたい → 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

Page 29: Elmで始めるFunctional Reactive Programming

(おまけ) 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/ を開く

Page 30: Elmで始めるFunctional Reactive Programming

参考文献

!   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