Functional Reactive ProgrammingとElm

この記事は Elm Advent Calendar 2016 11日目の記事です。

# まえがき

ElmはかつてFunctional Reactive Programmingの本命と言われていました。しかし、ElmはFRPと袂を分かってしまいます。[A Farewell to FRP](http://elm-lang.org/blog/farewell-to-frp) という記事にその内容が記されています。
日本語訳も[こちら](http://qiita.com/chuck0523/items/28b07968a941d8d493d2)に出ているので、ぜひ目を通してみてください。

しかし、Elm を学んで幾つかアプリを作ってみるという経験を通して、 Elm（Elmアーキテクチャ）の本質はFRPであると強く思うようになりました。

# Functional Reactive Programming とは

FRPには決定的な説明はなく、様々な形でその概念を説明しようという試みがなされています。例えば、[Wikipedia](https://en.wikipedia.org/wiki/Functional_reactive_programming)には

> __Functional reactive programming__ (**FRP**) is a programming paradigm for reactive programming (asynchronous data-flow programming) using the building blocks of functional programming (e.g. map, reduce, filter)

とあり、[Haskell Wiki](https://wiki.haskell.org/Functional_Reactive_Programming)には

> Functional Reactive Programming (FRP) integrates time flow and compositional events into functional programming.

という説明があります。

この2つの説明に共通しているのは、「FRPとは非同期的なデータストリームを扱うプログラミングパラダイムである」という点ではないかと思われます。

では、その「データストリーム」とは一体何なのでしょうか。以下、非同期的なデータストリームについて触れた上で、その次にElmアーキテクチャとの関連を考えてみたいと思います。

## 非同期的なデータストリーム

FRPという概念が最初に提唱されたのは1997年の[Functional Reactive Animation](http://conal.net/papers/icfp97/icfp97.pdf)という論文です。ユーザーからのインタラクティブな操作を関数として操作するため、BehaviorとEventという第一級の値が考えられました。その定義はだいたい次のようになります。

$Time \equiv \left\\{ t \in R | t > 0 \right\\}$

$Behavior \ a \equiv Time \rightarrow a$

$Event \ a \equiv List(Time \times a)$

Timeとは時間を表し、Behaviorは時間の関数、そしてEventは時間とペアになった無限リスト（すなわちストリーム）と考えられます。これから、非同期的なデータストリームとは、時間と値がペアになった無限リストであるということができます。

## Elmアーキテクチャ

Elmアーキテクチャはリアクティブなアプリケーションを作成する上で、我々にとって使いやすいパラダイムを提示してくれました。
FRPを全面に出していた以前よりもとっつきやすく、それぞれの要素を意識してプログラミングすれば良いので、より書きやすくなったのではないかと思います。
しかし、ElmアーキテクチャはFRPを知ると、よりアーキテクチャ自体の理解が進むのではないのかと思います。非同期的なデータフロープログラミングであるということを念頭に置くだけでも、Elmアーキテクチャのそれぞれの要素の相互関係がわかりやすくなるのではないでしょうか。

まず簡単にElmアーキテクチャについて解説します。
次に、ElmアーキテクチャとFRPを結びつけて捉えてみます。Elmアーキテクチャを構成するのに重要な__Model__ 、__Update__ と __Subscription__ を中心に考察します。

### Elmアーキテクチャの簡単な説明

#### __Messages__

アプリケーションを操作させるためのトリガーとなるもので、 Updateでハンドリングします。

#### __Model__
Modelはアプリケーションの状態を表しており、その中でもinitは初期状態を表しています。

#### __Update__
Messagesを受け取って新しいModelを返します。
場合によっては新しいCommandを発行します。

#### __Command__
外に出す命令、コマンドのことで、DBの検索やTaskを実行します。

#### __View__
HTMLとして状態を表現します。

#### __Subscription__
マウスイベント、キーボードイベントや時間などの外部イベントをリッスンさせるための機構です。

#### __Main__
アプリケーションを実行します。


## ElmアーキテクチャとFRP

### __Model__ と __Update__

Elmアーキテクチャでいうところの __Model__ は、FRPとして解釈するとデータストリームに相当します。[Elmの公式チュートリアル](https://guide.elm-lang.org/architecture/)には

> __Model__ — the state of your application

とあります。Elm アーキテクチャでは __Model__ を状態と呼んでいますが、これは初心者であったときの私にとってはややわかりづらい説明でした。なぜなら、状態があるならそれはミュータブルな世界があって、それを破壊的に変更できる、という先入観があったからです。しかし、Elm アーキテクチャの __Model__ と __Update__ のシグネチャーを見てみましょう。

```haskell
model : Model
```

__Model__ については説明は不要だと思います。

```haskell
update : Msg -> Model -> Model
```

__Update__ については、メッセージと Model を順番に受け取って、新しい Model を返すというように読むことができます。したがって、状態を更新する、という説明はややわかりづらいのではないかと思われます。ElmアーキテクチャをFRPの延長として捉えるのであれば、__Update__ は __Model__ というデータストリームをハンドリングし、新しい __Model__ を返す関数と捉えるのがいいのではないでしょうか。

### __Subscription__

さらに、データストリームとして捉えるという方法は、__Subscription__ の挙動を理解する上で役に立つのではないでしょうか。
シグネチャーを見てみましょう。

```haskell
subscriptions : Model -> Sub Msg
```

__Model__ を受け取り、__Sub Msg__ を返します。クリックイベントやマウスイベントなどの外部イベントは、そもそも __Model__ には組み込まれていません。したがって、__Subscription__ は_無からストリームを作っている_と見て取れます。そして、それを __Update__ でハンドリングし、新しいストリームを返すと考えられます。

### __View__

__View__ のシグネチャーを見てみましょう。

```haskell
view : Model -> Html Msg
```

__View__ はストリームの任意の要素をレンダリングする存在そして捉えられます。無限リストを受け取って、ある時刻 $t$ の要素をHTMLに変換し我々に提示します。

## Elmアーキテクチャにおけるデータフロー

以上の説明を簡単な図にすると、次のようになるかと思います。無限リストの中の一つのセルにおけるデータの流れを図にしてみました。以下のような図が無限に連なっていると考えてください。
ModelがUpdateによって次々と更新され、途中SubscriptionをUpdateが受け取ってさらに新しいModelを構築しながら、それが最終的にViewによってレンダリングされます。
[![https://gyazo.com/57bcbd6e4b1728d7ca726e52620a1595](https://i.gyazo.com/57bcbd6e4b1728d7ca726e52620a1595.png)](https://gyazo.com/57bcbd6e4b1728d7ca726e52620a1595)


# 参考

- [Elm Tutorial](https://www.gitbook.com/book/sporto/elm-tutorial)
- [FRPの話 - maoeのブログ](http://maoe.hatenadiary.jp/entry/2012/12/24/011414)