28

モナドスタックをどのように設計および構築しますか? 初めて、現実世界の問題を解決するために (トランスフォーマーを使用して) モナド スタックを構築する必要がありますが、どの順序でトランスフォーマーをスタックするか完全にはわかりません。ご存知のように、計算に kind がある限り* -> *、基本的には何でもトランスフォーマーの内部モナドの役割を果たすことができます。したがって、いくつかの質問があります。

  • 特定のトランスフォーマーをスタックの一番上に置く必要があります (例: ReaderT? WriterT?)。
  • 設計を推進するものは何ですか? 直感?種類?(たとえば、API のニーズに応じてスタックを形成します)
  • すべてのスタックは (ある程度) 相互に同形ですか? それとも、スタックを間違って構築すると、特定の基礎となるモナドを使用できなくなったり、大きな混乱が生じたりする可能性がありlift . lift . liftIO [...]ますか? 私の直感では、トランスフォーマーがいくつかのインスタンス (MonadReader、MonadIO など、ほとんどのトランスフォーマーがmtlそうであるように) を派生させる場合、トランスフォーマーをどの順序で配置しても問題ないはずです。

ベテランの Haskeller から、ベスト プラクティスや経験則について聞くことに興味があります。

forever $ print "Thanks!"

A.

4

2 に答える 2

12

これはかなり広い質問です。作業するための基本的なアイデアをいくつか紹介します。

まず第一に、基本モナドを可能な限りポリモーフィックに保つことをお勧めします。これにより、純粋な設定と IO 設定の両方でコードを再利用できます。これにより、コードがより構成可能になります。のようなさまざまなクラスを使用するとMonadIO、コードをよりポリモーフィックに保つのにも役立ちます。これは一般的には良いことです。

注意すべき重要な点の 1 つは、モナド変換子の順序が実際にそのセマンティクスを制御するということです。私のお気に入りの例は、エラー処理のためにListT¹のようなものを組み合わせることです。が外側にあるEitherT場合、計算全体がエラーで失敗する可能性があります。外側にある場合、各ブランチは個別に失敗する可能性があります。したがって、トランスフォーマーの順序を変更するだけで、エラーが非決定性と相互作用する方法を実際に制御できます。ListTEitherT

使用しているモナド変換子が順序に依存しない場合 (たとえば、 と を組み合わせても大した問題にはならない、ReaderTWriterT私は信じています) は、耳で聞いてみて、アプリケーションに最適と思われるものを使用してください。これは、経験を積むことで容易になるような選択です。

¹: ListTfromにはいくつかの問題があるため、正しく行われControl.Monad.Transていると仮定します。ListT

于 2013-05-09T08:48:58.870 に答える