122
Help us understand the problem. What are the problem?

10年間使ってみて見えたHaskellの闇と光

はじめに

わたしがHaskellを使い始めてもうそろそろ10年目になります。(タイトルは多少サバを読んでいますね)
これまで使ってきた感想をまとめます。

Haskellのつらいところ

まずは愚痴らせてください。

コンパイルが遅い

  • 依存モジュールはすべてソースコードからビルドする必要があります。(バイナリ形式のモジュールはありません)
  • 最初のビルドに20分くらい待つのはザラです。
  • 複雑な型システムをつかうと型推論や型レベル計算に時間がかかります。
  • 高速なHaskellプログラムを書くためには多くの関数をインライン化する必要があります。最適化ビルドではインライン展開によってコードサイズが大きくなるので時間がかかります。

デバッグが難しい

  • 公式のGHCiデバッガはありますが、今のところIDEから簡単に利用できるわけではないですし、コンパイル済みのライブラリはデバッグできないです。
  • 近年スタックトレースも出せるようになりましたが、書き方を工夫しないとあまり有益な情報は得られません。
  • 基本はprintfデバッグに頼ることになりますが、多相関数の引数はShowできないことも多くデバッグのために型制約を追加するのも面倒です。
  • リソースリークやメモリリークの特定はさらに困難です。(そして割とよく起きる)

プロファイルがとりづらい

  • プロファイルを有効にするためには依存モジュールを含め再コンパイルが必要です。(シャワーをあびるか、Uber Eatsでも頼んで待ちましょう)
  • プロファイル実行は通常の2-3倍遅くなります。
  • プロファイルを有効化すると最適化が効かなくなって真のボトルネックがわからなくなることもあります。
  • サンクが溜まっているとプロファイルはよく嘘をつきます。適切な区切りでサンクを評価しましょう。

テストが書きにくい

  • (純粋な関数のテストは書きやすいです。QuickCheckも素晴らしいと思います。)
  • 関数の実装を上書きする事はできないのでテストが書きやすいように工夫して書く必要があります。

String型が遅い

  • String型はHaskell最大の設計ミスです。
  • 1文字40バイト消費するので油断しているとすぐボトルネックになります。
  • とりあえずData.Text使っておけばまあ問題ないと思います。
    • しかし、表示したい型がShowしか使えないことも多くてつらいです。

文字列型いくつあるんだよ

  • Haskellの文字列型:分類と特徴によると11種類あるらしいです。
  • 先述のとおり、一番標準っぽさそうなStringが一番ダメな子なのもつらいです。
  • Backpack (参考)というので解決できるそうでしたが、あんまり使われている話を聞かないですね。誰か知っていたら教えてください。

言語拡張が多すぎる

  • みなさんの端末でghc --supported-languages | grep -v '^No' | wc -wを実行してみてください。いくつになりましたか?私の手元では125でした。
  • 使うべきもの、注意して使うべきもの、すでにレガシーとなっているものが玉石混交となっており初心者に優しくないです。
  • 最後の言語仕様はHaskell2010です。流石に11年経つと実際に使われる拡張とのギャップが大きいです。
    • GHC2021 というのがもうすぐできるのである程度は解消される見込みです。

「使える」ライブラリが少ない

  • それなりにライブラリは充実していますが、「使える」ライブラリかどうか判断がつきません。
  • 有名ライブラリでもメンテナが少ないのでライブラリの更新スピードは遅いです。(マイナー言語の宿命ですね)

なぜそれでもHaskellを使うのか

ここまでいろいろと愚痴を述べてきましたが、私はHaskellをこれ以上ない素晴らしい言語だと思っています。

実用的な言語のなかでは最強クラスの型システム

  • GHCの型システムは本当に強力で、うまく型設計すればそれに導かれるように正しいプログラムをかけます。
  • 複雑なデータ型もunsafeCoerceをほとんど使わずに表現できます。(動的型づけさえも!)
  • プログラムの仕様変更も大抵は型を変更して型エラーを直せば動きます。

参照透明性

  • 変数の値が決して変わらないという性質はプログラムをリファクタリングする際に大きな安心感を与えてくれます。
  • 参照透明だからこそできる融合変換(参考)を使いこないしたときの万能感は格別です。

シンプルな構文と奥深さ

  • Haskellの項は本質的には関数か、パターンマッチしかありません。それ以外は全て糖衣構文です。
    • GHCのCore言語のASTでも9種類のコンストラクタしかないそうです。 (参考)
  • 高階関数を使えばいかなる共通した部分をも抜き出してDRYすることができます。これはHaskell(系言語)以外ではなかなか味わえない体験です。

  • 構文のシンプルさとは裏腹に毎年のように新しいプログラミング技術や言語拡張が生まれています。私の知っている範囲だけでも次のような新技術が生まれてきました。勉強をしていて飽きる事はありません。

    • ライブラリ
      • Lens
      • Free/Operational Monad
      • Functional Reactive Programming
      • Iteratee/Conduit
      • Extensible Effects
    • 言語拡張
      • TypeFamilies
      • DataKinds
      • OverloadedLabels
      • LinearTypes
      • PatternSynonyms

これから

残念ながらHaskellがRustのような成功を収めることは今後もないでしょう。
しかし、Haskellの発展は止まる気配はありませんし、Haskellで生み出されたプログラミング技術が他の言語にも取り込まれていく事でしょう。
一生極め続けられる言語である事は自信をもって保証できます。
この記事を読んでHaskellに興味を持ってもらえる人が増えれば幸いです。
また野生のHaskellerのマサカリもお待ちしてます。

Why not register and get more from Qiita?
  1. We will deliver articles that match you
    By following users and tags, you can catch up information on technical fields that you are interested in as a whole
  2. you can read useful information later efficiently
    By "stocking" the articles you like, you can search right away
122
Help us understand the problem. What are the problem?