bheklilrの答えは、モナド変圧器がモナドでないものを生成する例を私に与えました。モナドでないもののよく知られている例はZipList
です。
import Control.Applicative
import Control.Arrow ((***))
import Control.Monad
import Control.Monad.Trans
-- | A list where each step is produced by a monadic action.
data ListT m a = Nil | Cons (m (a, ListT m a))
実際にはモナドストリームです。そして、それは簡単にFunctor
とApplicative
instance Monad m => Functor (ListT m) where
fmap f Nil = Nil
fmap f (Cons k) = Cons $ (f *** fmap f) `liftM` k
instance Monad m => Applicative (ListT m) where
pure x = Cons $ return (x, pure x)
Cons mf <*> Cons mx = Cons $ do
(f, fs) <- mf
(x, xs) <- mx
return (f x, fs <*> xs)
_ <*> _ = Nil
が、明らかではないモナドにすることができます。したがって、MonadTrans
というインスタンスは、モナドをApplicative
だけに変換します。
instance MonadTrans ListT where
lift mx = Cons $ (\x -> (x, lift mx)) `liftM` mx
(この全体のことは私がコンジット-余分の実験ZipSink
も素敵な一例であることを実感しました。)
しかし、これは別の問題を提起:私たちは、このようなをしたい場合変圧器、どの法律に従うべきですか? MonadTrans
のための法律がそう私たちのケースでは、我々は、私はと言うことは、他の2つの答えに反対するつもりだ
lift (f `liftM` x) = fmap f (lift x)
lift . return = pure
lift (m `ap` f) = lift m <*> lift f
クラスを作ることだった疑いがありますか?それは厳密にはあまり一般的ではないでしょうし、私はそれから何の利益も見ません。 –
@ JohnL主に['MonadTrans'の法律](http://hackage.haskell.org/packages/archive/transformers/0.3.0.0/doc/html/Control-Monad-Trans-Class.html#t:MonadTrans)モナドで表現されるので、結果はモナドでなければなりません。もしそうでなければ、法律は表現することさえできません。しかし、bheklilrは答えに良い点を示し、それに基づいて私は 'Monad' - >' Applicative'トランスを生成する[例](http://stackoverflow.com/a/18495255/1333025)を作ったのです。しかし、これは異なる法律を定式化する必要があることを意味します。 –