| Prev: モナド変換子 | TOC: 目次 | Next: モナド変換子の解剖 |
Haskell の base ライブラリは、モナド変換子を表わすクラスと標準モナドの 特定の変換子版を表わすクラスという形式でモナド変換子をサポートしています。
MonadTrans クラスは
Control.Monad.Trans
で定義されており、関数 lift のみを提供しています。
lift 関数は、内部モナドにあるモナド計算を合成モナドへ
もちあげます。
class MonadTrans t where
lift :: (Monad m) => m a -> t m a
|
入出力演算をもちあげるのに最適化をサポートするモナドは
MonadIO クラスのメンバとして定義されており、
liftIO 関数を定義しています。
class (Monad m) => MonadIO m where
liftIO :: IO a -> m a
|
モナドテンプレートライブラリの標準モナドは、すべて、その非変換子
バージョンと一貫性のある方法で定義された変換子バージョンを持ちます。
しかしながら、すべてのモナド変換子が同じ変換に適用できるというのは
真実ではありません。すでに、ContT 変換子が
(a->r)->r という形式の継続を
(a->m r)->m r という形式の継続に変換されるのを
見ました。StateT 変換子はそれとは違います。
それは、s->(a,s) という形式の状態変換関数を
s->m (a,s) という形式の状態変換関数に変換します。
一般的には、あるモナドの変換子バージョンを生成するための万能の公式という
ものは存在しません。— おのおのの変換子の形式はその非変換子版の
型のコンテキストにおいて筋の通るのは何かということに依存しています。
| 標準モナド | 変換子バージョン | 元の型 | 合成された型 |
|---|---|---|---|
| Error | ErrorT | Either e a |
m (Either e a) |
| State | StateT | s -> (a,s) |
s -> m (a,s) |
| Reader | ReaderT | r -> a |
r -> m a |
| Writer | WriterT | (a,w) |
m (a,w) |
| Cont | ContT | (a -> r) -> r |
(a -> m r) -> m r |
モナドを合成するとき、その順番は重要です。
StateT s (Error e) と
ErrorT e (State s) は別物です。
最初のものが合成するのは
s -> Error e (a,s)
という型で、その計算は、新しい状態を返すか、エラーを発生させるかです。
二つ目のものが合成するのは、
s -> (Error e a,s) という型で、
その計算は常に新しい状態を返し、かつ、値はエラーあるいは通常の値の
どちらかになります。
| Prev: モナド変換子 | TOC: 目次 | Next: モナド変換子の解剖 |