Haskell
purescript
Elm

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

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

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

Elm

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

PureScript

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

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

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

さいごに

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