プロダクションでHaskellを8年使った後、OCamlを8カ月使ってみた感想(2023)
(chshersh.com)- ある開発者がプロダクションで Haskellを8年、OCamlを8カ月使った経験をもとに、2つの関数型言語の実際の開発感覚を比較
- Haskellはより簡潔な構文と強力な型機能を提供する一方、選択肢が多く、設計や抽象化に気を取られやすい
- OCamlは機能の数こそ少ないものの、第一級モジュールと実用的な可変性、予測しやすいコードスタイルにより、実装に集中しやすいと評価
- エコシステムはHaskellの方が大きいが、ライブラリ選びが独立した技術のように感じられることがあり、OCamlは小さくても必要なツールが想像以上によく動く
- どちらの言語も主流言語より小さく、標準ライブラリは最小構成に近いが、特定SDKへの依存が大きくなければ、産業用アプリ開発にも十分使える
比較の出発点
- 基準はプロダクションで Haskellを8年、OCamlを8カ月使った経験
- 比較軸は構文、言語機能、エコシステム、ツール、コンパイラメッセージ、標準ライブラリ
- どちらの言語も実際の産業上の要求を支えられるほど発展しているが、現在の好みはOCaml寄り
構文:Haskellはより簡潔で、OCamlにもML系の利点がある
- Haskellは非常に少ない文字数でアイデアを表現でき、構文上の優雅さを強く感じる
- OCamlも ML系 言語として優れているが、Haskellの方がより暗黙的(tacit)なスタイルを提供する
- 文字列中の数値を合計する例では、Haskellは
sum . map read . wordsと短く表現し、OCamlはパイプラインで文字列の分割、変換、畳み込みの過程を明示する - 二分木の型定義は、どちらの言語も 代数的データ型 を自然に表現する
- パースの例では、どちらの言語もパターンマッチとオプション値を使うが、Haskellはdo記法と
guard、OCamlはOption.bindと明示的なmatchを使う
機能:Haskellは豊富で、OCamlは気が散りにくい
- Haskellは機能の数が非常に多く、比較対象としてC++が思い浮かぶほど
- 多くの機能は問題を精緻に解くための道具になるが、実装に入る前に解法の設計方法そのものを考えさせられることがある
- Haskellでは
TypeFamilies、DataKinds、GADTsといった選択肢を前に、設計にのめり込みやすい - 既存のOCamlプロジェクトで悪い状況といえば、たいてい変数名不足、ドキュメント不足、200行以上の関数といった程度で、対処可能なレベルと見られる
- 反対に既存のHaskellプロジェクトでは、8年の経験があっても備えにくい複雑さ に出会うことがある
- この違いにより、OCamlの方が生産的だと感じる
-
両言語が共有する機能
- 式中心の構文、デフォルトの不変性、高階関数、匿名関数、代数的データ型、パターンマッチをいずれも提供する
- パラメトリック多相、型推論、モナド構文糖、ガベージコレクタ、マルチスレッディング、GADTsも共通して利用できる
-
Haskell側でより目立つ機能
- Haskellはデフォルトの純粋性、合成可能な遅延評価、型クラス、高階kind型、選択式の言語拡張を提供する
- 強力な機能を多く備える分、プロジェクトごとに抽象化の方法が大きく変わりうる
-
OCaml側でより目立つ機能
- OCamlは 第一級モジュール(first-class modules)、多相バリアント(polymorphic variants)、オブジェクト、クラスと継承、使いやすい可変性を提供する
- 機能の幅はHaskellより狭いが、コードベースを予測しやすいという利点につながっている
エコシステム:Haskellはより大きく、OCamlには必要な解法がある
- どちらの言語もニッチな関数型プログラミング言語であり、最新フレームワークで第一級のサポートを期待するのは難しい
- それでも一般的な作業の大半には解法があり、場合によってはカスタムバインディングを追加で書く必要がある
- OCamlでも次のように実務で必要なパッケージを見つけられる
- otoml: TOMLパーサ
- Mint Tea: TUIフレームワーク
- ocaml-opentelemetry: OpenTelemetry計装
- awsm: OCaml AWSクライアント
- petrol: 高速なOCaml SQL API
- Haskellのエコシステムには、パッケージやすぐ使える解法がより多い
- Stripe APIのクライアントライブラリはHaskellが13個、OCamlは1個で、OCaml側は最後の変更が8年前のため、実質的には0個に近いと見られる
- Haskellでは解法を見つけた後も、多すぎる選択肢 の中からどのライブラリを選ぶか判断しなければならない
- ライブラリ選びが独立した技術のように扱われるほどで、ライブラリ評価方法をまとめた記事もある
- 新しいHaskellライブラリは、別の問題を解くためというより、別の抽象化や新機能で異なる書き方をしたいという理由で生まれることが多い
- GitHub APIクライアントを作ってJSONを大量にパースすることより、comonadsでloggerを設計することの方が面白い場合もある
ツール:Haskellは強力だが波が大きく、OCamlはよく動く
- Haskellのツールには、強力な利点と使い勝手の問題が共存している
- Hoogle は型シグネチャだけでエコシステム全体を検索できる強力なツール
- 一方で、ビルドツールのエラーメッセージ、動いているプロジェクトでビルドプランを見つけられない状況、パッケージ変更後のIDE再コンパイル、特定バージョンの標準ライブラリドキュメント不在といった問題がある
- Haskellのツール利用体験には、他の言語がこうしたツールなしでどう使われているのかと驚く瞬間と、Haskellユーザーが必須の使いやすさなしでどう過ごしているのかと驚く瞬間が同居している
- OCamlはエコシステムがより小さいため、動くものを見つけるたびに驚きがある
- LSPベースの VSCode OCamlプラグイン は追加調整なしで動作し、問題はなかった
- OCamlツールの導入体験が最高に快適というわけではないが、直感的で堅牢であり、ほとんどの場合きちんと動く
-
ツール比較
- コンパイラ:OCamlは ocaml、Haskellは ghc
- REPL:OCamlは utop、Haskellは ghci
- ビルドツール:OCamlは dune、Haskellは cabal と stack
- パッケージマネージャとリポジトリ:OCamlは opam、Haskellは cabal と Hackage
- リンター:OCamlは zanuda、Haskellは hlint
- フォーマッタ:OCamlは ocamlformat と topiary、Haskellは fourmolu、stylish-haskell、hindent、ormolu
- 型検索とコード検索:OCamlは Sherlodoc と Sherlocode、Haskellは Hoogle と Hackage Search
- オンラインプレイグラウンドとLSP:OCamlは TryOCaml と ocaml-lsp、Haskellは Haskell Playground と HLS
コンパイラメッセージ:Haskellは冗長で、OCamlは簡潔
- 関数型言語においてコンパイラは、コードが意図した前提をなぜ満たさないのかを理解するための重要な道具
- したがってエラーメッセージは、必要な情報をアクセスしやすい形で示すべき
- Haskellのコンパイラメッセージは文脈情報が多く冗長で、重複した情報や散漫な情報を含む傾向がある
- OCamlのコンパイラメッセージはかなり簡潔で、時には 簡潔すぎる
- エラー例のプログラムは、Haskellの
x = 1 + [3, 1, 2]とOCamlのlet x = 1 + [3; 1; 2]のように、整数とリストを足そうとするコード
標準ライブラリ:どちらも最小構成で、ドキュメント品質はHaskellが目立つ
- 標準ライブラリは、その言語での最初のプログラムとその後の利用体験を形づくる
- 優れた標準ライブラリはプログラミング言語の成功の基盤であり、不十分な標準ライブラリは代替標準ライブラリをめぐる議論を生み続けることがある
- 望ましい標準ライブラリは batteries-included 方式に近いべきだと見ている
- 欲しい構成には、Option相当の型、UTF-8文字列、MapとHashMap、JSONとXMLパーサ、非同期プリミティブなどが含まれる
- ビルドツールと依存関係追跡の実装を学びたくないなら、標準ライブラリにはより多くの機能が必要
- Build Systems a la Carteは、依存関係トラッカーとビルドツールの領域を分析した資料
- HaskellとOCamlのどちらも、標準ライブラリは比較的最小構成
- HaskellにはMapとHashMapが含まれない
- OCamlにはnon-empty listsとBitraversableがない
- Haskellの標準ライブラリは
baseで、OCamlは OCaml standard library を使う - Haskellのドキュメント品質は、熟練開発者でも驚くほど良い場合がある
- Haskellのドキュメントにはソースコードへ移動できる機能などの利点もあり、OCamlにもそうした機能が準備中だと聞いたという
-
ドキュメント例
- Haskell Listドキュメント例
- OCaml Listドキュメント例
- 結果が明白な関数であっても、例中心のドキュメントはAPIをどう活用するかをすぐに把握させてくれる
結論:どちらも産業用に使えるが、現在の好みはOCaml
- どちらの言語も実際の産業上の要求を支えられるほど大きく発展している
- 主流言語と比べれば、依然として小さな言語に属する
- 特定SDKの存在に致命的に依存しないなら、どちらの言語を選んでも次のアプリを楽しく開発できる
- 現在は OCaml の方が、実際に何かを作ることに集中しやすいと評価されている
まだコメントはありません。