関数型リアクティブプログラミングにさよならを

以下の記事は、[Evanの許可を得て](https://twitter.com/czaplic/status/731040254224797696) [A Farewell to FRP](http://elm-lang.org/blog/farewell-to-frp)を訳したものです。
訳者はElm初心者ですので、理解が足りてない箇所があるかと思われます。何か誤りやベターな記述がありましたら、ご指摘いただけると幸いです。


ちなみに、関数型リアクティブプログラミング全般の話ではなく、あくまでElmに関する話です。


----


[Elmアーキテクチャ](http://guide.elm-lang.org/architecture/index.html)はWebアプリを設計するためのシンプルな手法です。Elmを書くならばElmアーキテクチャに沿うのが普通ですし、ElmはReduxに影響を与えています。ElmアーキテクチャはもはやJavaScriptを書く際の手法としても人気になりつつあります。しかし、いまだにこんな疑問を耳にすることがあります。WebSocketをElmアーキテクチャで使うにはどうすればいいのか？あるいはGlaphQLは？あるいはGeolocationは？
__今日Elmのバージョン0.17がリリースされました。__そして、バージョン0.17には上記の疑問をうまく解決するようなsubscriptionsが導入されました。ライブラリがリソース管理を行っている間、subscriptionsはコンポーネントを待機させるのです。subscriptionがいかにしてWebSocketと簡潔に機能し合うかについては、後ほど見ていきましょう。

ここで注目すべきことは、__今やカンタンにElmを学び、そして使うことができるようになったということです。__subscriptionを思いついた時、Elmにおけるすべての難しい概念（Signal、アドレス、ポート）は１つのシンプルな考えに集約できるのだと気付きました。Elmは使いやすさを重視しているので、より少ない概念への道筋が開けた時は喜びを感じました。分かりやすく言うと、__ Signalに関する全てが、よりシンプルで良いものへと置き換えられたのです。__この知らせに対して、おそらく２つの反応があります。

1. __なんてこった。今までのコードは動くのか？__ おそらくコードの95%はまったく今までどおりで大丈夫です。[アップデートプラン](https://github.com/elm-lang/elm-platform/blob/master/upgrade-docs/0.17.md)を参考にしてください。アップデートはたいした問題ではありません。
2. __こいつは何を言っているんだ？関数型リアクティブプログラミング？Signal？__ 今回のリリースに関して、関数型リアクティブプログラミングやSignalについて学ぶ必要なんてないということです。Elmは今やカンタンなのです。

いずれにせよ、まずは新しいバージョンでElmがどのように動くのかをお見せするのが良いでしょう。Elmは今まで以上に多くのことが可能になりましたが、今まで以上にシンプルでもあります。Elmがこのような変化を遂げたことを嬉しく思いますし、Elmを楽しんでくださると幸いです。

```
Elm 0.17に含まれるその他の機能。

・ より速いHTMLレンダリング（数値はまもなく公開されます。）
・ Geolocation、ページ可視性、Web socketsのライブラリ
・ 生成されるJSが小さくなり、GoogleのClosure Compilerで動くようになりました。
・ 生成されるJSがRequireJSやCommonJSに対応。
・ GraphQLやElixir、Phoenixの代わりとなる機能。
・ 改善されたドキュメント。
・ JSONファイルのデコード失敗時の役立つメッセージ。
```

### subscriptionとは何か？

subscriptionはコンポーネントに対して、メッセージを待たせるための手法です。たとえば、現在時刻や位置の変更、WebSocketのメッセージなどを定期的に受け取ることができます。
もっともシンプルなsubscriptionは時間です。時間のsubscriptionは、以下のSVG時計の根幹となるものです。

(略。本家を参照下さい。)

SVG時計のコードについては、[こちらのソースコード](http://elm-lang.org/examples/time)をご覧ください。これはElmアーキテクチャに沿った典型的なElmのコードです。バージョン0.17で新しく追加されたのは、以下の定義部分だけです。

```hs
subscriptions : Model -> Sub Msg
subscriptions model =
  Time.every second Tick
```

現在のModelをベースとして、すべてのアクティブなsubscriptionを説明していきます。上記の例では、[Time.every](http://package.elm-lang.org/packages/elm-lang/core/4.0.0/Time#every)関数は現在時刻のsubscriptionをセットアップします。このsubscriptionは毎秒ごとに更新されます。新しい時刻は、マウスクリックやHTTPリクエストの結果としてのメッセージと同じように、update関数に組み込まれます。

subscription以外のElmアーキテクチャに関するものはすべて従来通りです。コンポーネントを受動的に待たせる方がカンタンです。 さらに他のケースを見ていきましょう。

### WebSocket

ここで、シンプルなチャットクライアントの例を見ていきましょう。人々が互いにおかしなことを言い合わないように、チャットサーバへとただメッセージを送る仕様としました。

(略。本家参照。)

サンプルのソースコードは[こちら](http://elm-lang.org/examples/websockets)です。時計の例と非常に似ていますが、WebSocketのコネクション管理を行っています。考えをめぐらすべき箇所は以下の関数だけです。

```hs
WebSocket.send "ws://echo.websocket.org" input
WebSocket.listen "ws://echo.websocket.org" NewMessage
```

１行目はメッセージを送信する関数で、２行目がメッセージのsubscriptionです。どちらのケースでも、チャットサーバのアドレスとメッセージの値を与えています。```send```には送信したい文字列だけを与えます。```listen```はタグ付けを行う関数を持ちます。なので"hi"といったメッセージをサーバから受け取った時、```NewMessage "hi"```として```update```関数に紐付けられます。

驚くべきことは、__セットアップのためにたくさんのトリックを行うこと無く、完璧に機能するチャットクライアントを作ることができた__ということです。ただ、sendとlistenを行う。それだけです。ただし、もしあなたがJavaScriptにおける２つの選択肢を知っていれば、さほど驚くことではないかもしれませんが。

- __ブラウザAPIを使う__ ― まず新たなWebSocketを立ち上げます。そして、コネクションを開きます。```onerror```をつけるのをお忘れなく。これはコネクションが落ちた時にexponential backoff形式で再接続を行います。そしてコネクションが落ちているときは決してメッセージを```send```しないでください。実行時エラーになります。キューに積んでおいて、後ほど送信する必要があります。キューが実装されたなら完成です。あとはただ、どのコンポーネントにWebSocketをもたせればいいのか決めるだけです。そして、閉じるべき時にソケットがきちんと閉じていることも確かめましょう。
- __JSライブラリを使う__ ― ブラウザAPIを使うのはなんだか難しそうですね。では、同じようなライブラリを探してみましょう。[2000以上もの選択肢があるみたい](https://www.npmjs.com/search?q=websocket)ですね。幸い、私がいくつか試した所うまく動きました。

Elm用の[WebSocketパッケージ](http://package.elm-lang.org/packages/elm-lang/websocket/1.0.0/WebSocket)では、コネクションの子守は自動的に行われます。コネクションはサブスクライブされたときにオープンになりますし、サブスクライブがされなくなるとクローズになります。キューや再接続に関する処理も裏側で行ってくれます。

### もっとくわしく

手短ではありますが、以上がsubscriptionに関する導入でした。もし、ElmとElmアーキテクチャに何が起こっているのかを知りたければ、[An Introduction to Elm](http://guide.elm-lang.org/)をご覧下さい。[Elmアーキテクチャ](http://guide.elm-lang.org/architecture/index.html)に関する箇所は徐々にsubscription向けの内容になってきており、たくさんの好例が含まれています。
熟練のElmユーザは[アップデートプラン](https://github.com/elm-lang/elm-platform/blob/master/upgrade-docs/0.17.md)を読みましょう。[An Introduction to Elm](http://guide.elm-lang.org/)にもぜひ目を通してみてください。もちろんElmについては既にご存知でしょう。しかし、バージョン0.17においてElmの各機能がいかに素晴らしく結合されるかを、ガイドは実に上手く説明してくれるでしょう。特に、[Elmアーキテクチャ](http://guide.elm-lang.org/architecture/index.html)と[ports](http://guide.elm-lang.org/interop/javascript.html)の箇所は必見です。

最後に。いつでも[SlackのElmチャンネル](http://elmlang.herokuapp.com/)に来てくださいね！私たちは新しいことを学んだり、古いコードを書き換えようとする人々をぜひ助けたいです。質門を投げかけてみてください。


### 関数型リアクティブプログラミングにさよならを

Elmは楽しいプロジェクトを作成するためのものです。こちらの[raicaster](https://twitter.com/krisajenkins/status/726043742180925440)が良い例です。わくわくして人にシェアしたくなるようなプロジェクトです。プログラミングをすることがわくわくするようなプロジェクトです！そのため、私はいつでも自分に問いかけてきました。どうすればElmをシンプルにすることができるのか？Elmを学びやすいものにするにはどうすればいいのか？どうすればElmをより楽しいものにできるのか。プロトタイプしやすくするには？信頼性を高めるためには？
これらの疑問に対する私の執着がElmの設計思想と成功の肝であるように思われます。

2011年に[こちらの論文](http://elm-lang.org/papers/concurrent-frp.pdf)に取りかかりはじめた時、関数型リアクティブプログラミング(FRP)と呼ばれる分野に出会いました。その手法をもっともシンプルな形式に落としこむことで、似たような関数型の言語よりも学びやすいものを作ることに私は帰着しました。難解な概念の積み重ねであるSignalは、Elmには必要なかったのです。

Elmを教えたことがある人ならきっと、Signalがつまづきやすいポイントの１つであることに同意してくれると思います。それらのつまづきやすい難所は、類似の言語に比べてElmをカンタンにしました。しかし、Elm自体をカンタンにしたわけではありません。

Elmアーキテクチャが現れた時、SignalはElmでのプログラミングにおいて全く必要のないものだと明確になりました。[start-appパッケージ]()を使えば、Signalはあとで学べばよくなります。start-appパッケージのリリースはそれによって何が起こるのかを知るための実験だったのです。結果は上々でした！多くの人びとが、Signalについてじっくりと学ばずとも、素晴らしいElmエンジニアとなったのです。Signalは不要だったのです。Elm 0.17は進むべき方向へと次のステップを踏み出しました。

つまるところSignalをなくすことは可能でした。なぜなら、Elmは並行性を明示的に強調する方向へと動き出したからです。この萌芽は論文中で明らかですが、実際に車輪が回りだしたのはElmにタスクが実装されたバージョン0.15からです。0.15のリリースではまた、スケジューラーも導入されました。Elmのバージョン0.17においては、このスケジューラーが大いに改善されました。ErlangやElixirで使われているBEAM VMから得た示唆をベースにしています。```Process```モジュールのドキュメントにおいて、[どのように動くのか](http://package.elm-lang.org/packages/elm-lang/core/4.0.0/Process)や[将来的な動き](http://package.elm-lang.org/packages/elm-lang/core/4.0.0/Process#future-plans)について詳細を読むことができます。スケジューラーはまた、[effect managers](http://guide.elm-lang.org/effect_managers/index.html)の基盤でもあります。effect managersはそもそもsubscriptionを可能にするものでもあります。このあたりのドキュメントをもっと充実させたいのですが、幸いあなたはこれらのことを知ることなくElmのエキスパートになることができます。私の論文の[Concurrent FRP](http://elm-lang.org/papers/concurrent-frp.pdf)の項で述べたように、ゴールは並行性の旨みをカンタンに手にすることです。

関数型リアクティブプログラミングに関するElm？いえ。そのような日々は終わりました。Elmは並行性を真剣に考えている単なる関数型言語です。ユーザの視点から見ればElmは非常にフレンドリーな関数型言語です！