ElmとPureScript、どっちを選べばいいんだよ

![usagiunagi.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/64695/e2686823-00ac-46eb-4aa5-36de03ad2388.png)

(※アイキャッチ画像は、この記事に関係あるようで関係ないウサギ対ウナギ画像です)

アドベントカレンダー『Elm2』の昨日の記事は、ababさんの『[Elmで副作用を扱う仕組みCmdがとっても良い理由](https://qiita.com/ababup1192/items/2b86ade96651716fc3a8)』でした。副作用のある部分とない部分を分離する「純粋」な言語は、作用を扱うのが面倒くさい言語だと思われがちですが、実は作用を扱うのがとても上手なんですよね。Elmの`Cmd`は、Haskellみたいにモナモナせずにシンプルに作用を扱う方法としてElmがたどり着いた、ひとつの解答であります。

さて、Elm と PureScript は、どちらも AltJS にして Haskell の直系の子孫であり、そしてどちらも正格評価でありレコード型のような機能を取り込んでいるなど、共通点の多い言語たちでもあります。このどちらを選べばいいのか、迷っている人もいるのではないでしょうか。そんな方のために、それぞれの特徴をまとめてみました。もし参考になれば幸いです。

## Elm

* **ひとことでいうとシンプル＆セーフ**。Haskell の子孫であるのを辞め、関数型プログラミング言語を名乗るのを辞め、リアクティブプログラミングを辞めた言語。だってそういうの難しいし。無くてもなんとでもなるし。`Functor`とか`Monad`とか`Category`とか、理想は結構だけどHaskellの型クラスは抽象的すぎです。型クラスなんてなくても、それぞれの型ごとの`map`や`andThen`を使い分ければいいだけです。難しいところはぜんぜんないので、(Elm自身は積極的に『関数型』を名乗るのは止めましたが)いわゆる関数型プログラミング言語の入門用としても最適な言語だといえるでしょう。
* **自分の爪すら自分で切れないような安全性**。実行時エラーを見ることはほぼありません。Elm製アプリケーションで実行時エラーを見ることがあるとしたら、それは port の外の JavaScript の部分で起こります。外界でどんな地獄が繰り広げられていようが、Elm の世界はお花畑の天国です。実用的な言語の中では、実行時エラーへの防御力はElmは私が知る限り史上最強だと思います。
* **関数型プログラミング初心者、Haskell未経験者は Elm 一択**。いきなり PureScript につっこむのは無謀極まりないです。まずは Elm から始めて、物足りなくなったら PureScript に挑めばいいのです。Elmの言語仕様はとてもシンプルで、最近のバージョンアップでは機能が減っているくらいです。これほど入門しやすい言語はなかなかありません。
* **AltJS といえど Nodeは無理**。いや`Platform.worker`を使えばまったく無理というわけではないものの、実験的な機能にとどまっていて、いつ首を切られるかわからない状態です。サーバサイドアプリケーションのフレームワークもないようですし、サーバサイドは諦めましょう。
* **既存のJavaScript資産を流用するのはかなり面倒くさい**。欲しい機能があったときにはElmのパッケージをインストールすれば一発、というわけにはいかないことが多いです。`LocalStorage`や`Canvas`などは特に使用頻度が高いのに、今のところport越しにしか使えません。まったく不可能とまではいいませんが、隔靴掻痒とはこのことです。既存のライブラリを気軽にラップすることは諦めましょう。**Elmの性質に合わせて設計された公式のAPIが提供されている場合はとてもうまくいきますが、公式で提供されていない機能を使おうとすると途端に面倒くさいことになります**。`WebAudio`のようなドラフト段階の機能を使いたい時も、ポートで凌ぐしかありません。気長に待っていれば、いつか公式のパッケージが提供されて、使いやすいAPIが手に入るでしょう。いつになるかはわかりませんが。オリジナル開発者のエヴァンさんは、APIを作るのにとても慎重です。何度もプロトタイプを作ってはdeprecatedにし、本当に上手くいくと確信できた最低限のAPIだけを公式に格上げします。一方で失敗したと思ったものは容赦なく削除します。
* **コンパイルしてバンドルされた最終的なJavaScriptコードのサイズはやや大きめ**。ツリーシェイキングは効くので超大きいというわけではありませんが、PureScriptに比べるとランタイムとでも呼べそうなコードが多少くっついてきます。といってもツリーシェイキングのロクに効かない素のJavaScriptよりはマシだと思います。
* **UIフレームワークは事実上ひとつ**。フレームワークの選択に迷うことはありませんし、その唯一のフレームワークの品質は申し分ないので、むしろフレームワークの選択肢なんて必要なの？という気持ちに。
* 型レベルプログラミングはほぼ不可能。それなりにボイラープレートが生じますが、筋肉で解決しましょう。
* **残念なググラビリティ**。検索すると**楡の木**ばっかりヒットします。短い一般名詞なので、SNSでもかなり検索しにくいです。
* **コミュニティが PureScript より大きい**。この一点だけでも、 Elm を選ぶ充分な理由になるでしょう。戦いは数だよ兄貴！
* **充実したエコシステム**。専用のパッケージマネージャや`create-elm-app`や`elm-format`、`elm-minify`のようなツールも揃っています。Atom用の拡張`elmjutsu`はとても強力です。公式のドキュメント`An Introduction to Elm`ももちろん最新のコンパイラに対応しており、精力的に更新されています。至れりつくせりです。
* **創始者が現役**。エヴァンさんはいまも第一線でゴリゴリとコンパイラとライブラリとドキュメントを変更しまくっていて、追いかけるこっちがが大変なくらいです。

## PureScript 

* **ひとことでいうとパワフル＆ユニバーサル**。Haskell の魂を Haskell 以上に体現した存在。`Ring`だ！`Profunctor`だ！`Strong`だ！抽象度のぶっちぎれた型クラス群を操って、関数型プログラミングの極北に桃源郷を打ち立てろ！筋肉で汗臭いプログラミングをしている人たちを横目に、型レベルプログラミングでクレバー＆クールに解決するのがPureScript流。ウェブクライアントサイドもサーバサイドも書けて、オールインワンで万能の言語です。
* **自分の頭を撃ち抜く自由**。言語仕様としては Elm と同程度の安全性があって、Haskellのように`head`で死ぬとかパターンマッチングで落っこちるみたいな間の抜けたことはないのですが、`Effect`ではJavaScriptとほぼ同じように[`throw`](https://pursuit.purescript.org/packages/purescript-exceptions/4.0.0/docs/Effect.Exception#v:throw)で実行時エラー投げ放題のガバガバっぷりですし、作用ではなく純粋な計算においてすら、よく FFI の定義でミスって実行時エラーが飛んできます。JavaScript の API はどういうときに例外が起こるか厳格に明文化されていることが稀で、そういったライブラリを正しく FFI で包むことは現実的には困難なためです。言い換えれば、もし必要ならFFIを使えば純粋性を簡単に破壊できます。とはいっても、JavaScriptはもちろん他の大抵の言語よりははるかに安全です。Elmの安全性が特に飛び抜けているだけで、それに比べればちょっと危険かも、というくらい。
* **Haskell経験者だったり、関数型プログラミングの腕に覚えがあれば、ためらいなく PureScript に突っ込もう**。PureScriptは、Haskellの精神を受け継いでさらに研ぎ澄ました、「HaskellよりもHaskellらしい」言語です。「型クラスなんて要らない」なんてElmの負け惜しみなんか気にしないで、`RowToList`でボイラープレートを叩き壊せ！
* **Nodeを使いたいなら PureScript 一択**。サーバサイドもクライアントサイドもこれ一本。
* **コンパイルされてバンドルされた最終的なJavaScriptコードはElmよりもさらに小さいです**。これはPureScriptには『ランタイム』に相当する部分がまったくないためです。それが決め手になるほど大きな差ではありませんが、小さいのは確か。
* **UIフレームワークは選択可能**。Halogen、Pux、Thermite、自分の好きなライブラリを選ぼう。といっても、実際はHalogenだけあればだいたい事は足りるような気がしますが……。
* **強力な型レベルプログラミング**。たとえば、任意の型からそのJSONエンコーダを自動的に導出できます。いちいちデコーダを手書きするなんて汗臭いことはやってられない。型レベル計算でスマートに解決しましょう。
* **FFIで  JavaScript のライブラリをラップして PureScript から使うことが簡単にできます**。ライブラリが足りなかったら、JavaScriptのライブラリを流用して自分でFFIで包んで使えばいいだけです。**JavaScriptでできることは、PureScriptでも何不自由なくできると思ってしまっていいと思います**。PureScriptは『〇〇をしたい』という気持ちを『正しさ』で妨げたりはしません。それに、『純粋関数型言語』といっても、特に変な書き方になったりもしないので安心です。JavaScriptと一対一で対応するようなコードが書けます。WebAudioやWebGLといった新しいAPIも、FFIを使えばなんとでもなります。PureScript界隈ではJavaScriptのライブラリを気軽に包んだだけのパッケージがガンガン作られていますし、一方で、作ったはいいがうまく行かずに放棄されるパッケージも山のようにあります。そこにオリジナル開発者のフィルさんの方針が強力に働いているようなことはなく、誰であろうと気軽にパッケージを公開することができます。逆に言えば、実用的に使うならFFIは必修です。もちろん、先述したように、FFIは危険と隣り合わせですが。
* **申し分のないググラビリティ**。簡単にPureScriptの話題だけをヒットさせることができます。
* **コミュニティが Elm より小さい**。この一点だけを理由にPureScriptを諦めても仕方ないと思います。多勢に無勢とは、昔の人はよく言ったものです。はあ。
* **エコシステムはようやく揃いつつあるというところ**。以前はパッケージマネージャにBowerを使っていて、それがとても古さを感じさせていたのですが、Spagoの登場によってパッケージ管理まわりはようやく整いつつあります。ただ、他にも各種エディタ向けのプラグインなどもあるものの、Elmに比べると物足りない感じもあります。事実上の公式ドキュメントである`PureScript by Example`は最新の言語仕様に対応しておらず、コンパイルが通らないサンプルコードが少なくないです。つらすぎです。
* **創始者がコンパイラメンテナから引退**。コンパイラの開発はコミュニティに引き継がれて続いていますが……。フィルさんはまだPureScript界隈で活動していらっしゃいますが、とてもお忙しいそうです。つらい。まあバージョン 1.0 は目前で、今後極端な言語仕様の変更はなさそうではあります。そうはいってもつらい。



# では結局どちらを選べばいいの？

上の比較を読んでどちらかに確信が持てたらそれを使えばいいですし、迷っているならとりあえずElmから入って、それでもし物足りなければそのあとでPureScriptにも手を出せば、大失敗はないのではと思います。……っていうか両方やればいいじゃん！

# さいごに

明日の記事は miyamo さんの[『[Elm]Browser.Navigation.Key生成できない問題』](https://qiita.com/miyamo_madoka/items/ea4858638effc12dbc11)です！　私はこういう大きなカタマリでのテストをロクに書いていなかったので、この問題には気付きませんでした。でも確かにこれは地味に困りますね！