[解決済み】Template Haskellの何がそんなに悪いのか?
2022-04-04 13:02:09
質問
Haskellコミュニティでは、Template Haskellは不幸な利便性と捉えられることが多いようです。この点に関して私が観察したことを正確に言葉にするのは難しいのですが、以下のいくつかの例を考えてみてください。
- Template Haskellは、"The Ugly (but necessary)"にリストアップされ、質問に答えています。 Haskell (GHC) の拡張機能のうち、ユーザーが使用すべきもの/避けるべきものは何ですか?
- で一時的/劣後的な解決策とされたテンプレートHaskell。 newtype'd値の非ボックス化ベクトル スレッド (ライブラリメーリングリスト)
- Yesodは、Template Haskellに依存しすぎているとよく批判されます( ブログ記事 という意見に応えて)
Template Haskellを使って、通常のHaskellでは不可能なきれいな構文を可能にしたり、定型文を大幅に減らしたりしているブログ記事をいろいろと見てきました。では、なぜTemplate Haskellはこのように見下されているのでしょうか?何が好ましくないのでしょうか?どのような状況でTemplate Haskellを避けるべきなのか、またその理由は?
どうすれば解決するの?
Template Haskellを避ける理由の1つは、全体としてタイプセーフでないことです。
-
THコードの一部がどのようなHaskell ASTを生成するかは、それがどこに表示されるか以上にコントロールすることはできません。
Exp
を表す式であるかどうかはわからない。[Char]
または(a -> (forall b . b -> c))
といった具合に。関数が特定の型の式だけを生成する、関数宣言だけを生成する、データコンストラクタにマッチするパターンだけを生成する、などと表現できれば、THはより信頼できるものになるでしょう。 -
コンパイルできない式を生成することができます。自由変数を参照する式を生成しました。
foo
存在しない?運が悪いことに、実際にコード・ジェネレーターを使うときに、その特定のコードの生成のきっかけとなる状況下でしか、そのようなことは起こらないのです。また、ユニットテストも非常に困難です。
THはまた、まったくもって危険です。
-
コンパイル時に実行されるコードで、任意に
IO
ミサイルを撃ったり、クレジットカードを盗んだり。THエクスプロイトを探すために、ダウンロードしたすべてのCabalパッケージに目を通す必要はないでしょう。 - モジュールのプライベートな関数や定義にアクセスすることができ、場合によってはカプセル化を完全に破壊することができます。
それから、ライブラリ開発者としてTH関数を使うのが楽しくなくなるような問題もあります。
-
THのコードは必ずしもコンポーザブルではない。例えば、誰かがレンズのジェネレータを作ったとします。そのジェネレータは、他のTHコードではなく、エンドユーザーが直接呼び出すことができるような構造になっていることが多く、例えば、レンズを生成するための型コンストラクタのリストをパラメータとして受け取ります。このリストをコードで生成するのはやっかいです。
generateLenses [''Foo, ''Bar]
. -
開発者は
知っている
THのコードが構成できること。を書くことができるのをご存知でしょうか?
forM_ [''Foo, ''Bar] generateLens
?Q
は単なるモナドなので、その上で通常の関数をすべて使用することができます。それを知らない人がいるから、同じ機能を持つ関数のオーバーロード版をいくつも作ってしまい、ある種の肥大化を招いてしまう。また、ほとんどの人はジェネレータをQ
を書くようなものです。bla :: IO Int; bla = return 3
関数に必要以上の環境("environment")を与えることになり、関数のクライアントはその効果としてその環境を提供することを要求されます。
最後に、THの関数をエンドユーザーとして使うのが楽しくなくなるようなことがあります。
-
不透明度。TH関数に型がある場合
Q Dec
というのも、モジュールのトップレベルにはどんなものでも生成できてしまい、何が生成されるかは全くコントロールできないからです。 - モノリシック。開発者が許可しない限り、TH関数が生成する量をコントロールすることはできません。もし、データベース・インターフェースを生成する関数を見つけたとしたら と JSONシリアライゼーション・インターフェースの場合、「いや、私はデータベース・インターフェースだけが欲しいんだ、ありがとう、JSONインターフェースは自分で作るよ」とは言えません。
- 実行時間。THコードの実行には比較的長い時間がかかります。ファイルがコンパイルされるたびにコードが新たに解釈され、しばしば、実行中のTHコードが必要とする大量のパッケージがロードされなければなりません。このため、コンパイル時間がかなり遅くなります。
関連
-
[解決済み] Haskellにおける除算
-
[解決済み] HaskellでIntからsqrtを取得する
-
[解決済み] Haskell takeWhile + 1
-
[解決済み] モナドはエンドファンクタのカテゴリではただのモノイドですが、何か問題でも?
-
[解決済み] Project Eulerとの速度比較。CとPythonとErlangとHaskellの比較
-
[解決済み】Haskellの宣言におけるエクスクラメーションマークの意味とは?
-
[解決済み】Template Haskellの何がそんなに悪いのか?
-
[解決済み】Haskell: リスト、配列、ベクトル、シーケンス
-
[解決済み】テンプレートHaskellで関連する型の同義語を取得する
-
[解決済み】Haskellの入門編
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み] haskellでCharからIntに変換する
-
[解決済み] Haskellでwhileループに相当する文は何ですか?
-
[解決済み] Haskellの[]と':'とは何ですか?
-
[解決済み】代数的なデータ型の代数を悪用する - なぜこれが有効なのか?
-
[解決済み】GOTOはまだ有害と考えられている?[クローズド]
-
[解決済み】Haskellの宣言におけるエクスクラメーションマークの意味とは?
-
[解決済み】Not a Functor/Functor/Applicative/Monadの良い例?
-
[解決済み】一般的なHaskellの演算子で発音可能な名前はありますか?[クローズド]
-
[解決済み】なぜモナドが必要なのか?
-
[解決済み】Haskell の `data` と `newtype` の違いについて