私はHaskellを初めて使用しますが、モナド変換子の使用方法を理解しています。それでも、関数呼び出しにパラメーターを渡すことに対して、彼らが主張する利点をつかむのはまだ困難です。
wikiモナド変換子の説明に基づいて、基本的に次のように定義された構成オブジェクトがあります
data Config = Config Foo Bar Baz
この署名で関数を書く代わりに、それを渡すために
client_func :: Config -> IO ()
ReaderTモナド変換子を使用して署名を次のように変更します
client_func :: ReaderT Config IO ()
Configをプルすることは、への単なる呼び出しask
です。
関数呼び出しがからclient_func c
に変わりますrunReaderT client_func c
罰金。
しかし、なぜこれが私のアプリケーションを単純にするのですか?
1-多くの関数/モジュールをつなぎ合わせてアプリケーションを形成する場合、モナド変換子に関心があると思います。しかし、これが私の理解が止まるところです。誰かが光を当ててくれませんか?
2-モジュールが何らかの形式のAPIを公開して実装を非表示にし、(部分的に)独自の状態と環境を他のモジュールから非表示にする、Haskellで大規模なモジュラーアプリケーションを作成する方法に関するドキュメントが見つかりませんでした。ポインタはありますか?
(編集:Real World Haskellは、「..このアプローチ[モナド変換子] ...はより大きなプログラムに拡張できる」と述べていますが、その主張を示す明確な例はありません)
以下のクリス・テイラーの回答に続いて編集
クリスは、Config、StateなどをTransformerMonadにカプセル化することで2つの利点が得られる理由を完全に説明しています。
- これにより、上位レベルの関数が、呼び出す(サブ)関数に必要であるが、それ自体の使用には必要のないすべてのパラメーターを型アノテーションで維持する必要がなくなります(
getUserInput
関数を参照) 。 Writer
その結果、トランスフォーマーモナドのコンテンツの変更に対して、より高いレベルの関数の復元力が高まります(たとえば、より低いレベルの関数でのロギングを提供するために、それに追加したい場合)
これには、Transformerモナドの「内部」で実行されるようにすべての関数のシグネチャを変更するという犠牲が伴います。
したがって、質問1は完全にカバーされています。クリスありがとう。
質問2はこのSO投稿で回答されました