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
하지만 모나드. 따라서 모나드를 Applicative
으로 변환하는 MonadTrans
인스턴스가 있습니다.
instance MonadTrans ListT where
lift mx = Cons $ (\x -> (x, lift mx)) `liftM` mx
(이 모든 것은 나를 실험
ZipSink
도관-추가도 좋은 예입니다 것을 깨닫게했다.)
그러나, 이것은 또 다른 질문이 제기 : 우리는 원하는 경우 변압기, 그들은 어떤 법칙을 고수해야합니까? MonadTrans
에 대한 법률은 그래서 우리의 경우 우리가
lift (f `liftM` x) = fmap f (lift x)
lift . return = pure
lift (m `ap` f) = lift m <*> lift f
왜 결과가 모나드인지 확인 하시겠습니까? 그것은 엄격히 일반적이지 않으며, 나는 그것으로부터 어떤 이익도 보지 못합니다. –
@ JohnL 주로''MonadTrans' laws (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)를 만들었습니다. 그러나 이것은 우리가 다른 법칙들을 공식화 할 필요가 있음을 의미합니다. –