2012-12-18 2 views
3

다른 것들 중에서도 오류 기능을 가진 기본 모나드를 제공하는 모나드 변환기를 정의하고 싶습니다. 변형 된 모나드는 기본 모나드가 MonadPlus의 인스턴스 여야합니다. 그러나 MonTPlus 인스턴스를 정의하는 방법을 알아낼 수 없으므로 ErrorT 변환기가 두 개 이상의 대답을 반환합니다 (둘 이상의 대답이있는 경우). 내 두 시도는 아래 코드에 있습니다. 코드 끝에는 기본 모나드가 [] 인 경우 모나드 변환기가 어떻게 동작해야하는지 보여주는 문이 있습니다. 감사.ErrorT 상단에 변압기에 대한 MonadPlus 인스턴스 정의

import Control.Monad.Error 
import Control.Monad.Trans.Class 

data MyTrans m a = MyTrans {runMyTrans :: ErrorT String m a} 

instance Monad m => Monad (MyTrans m) where 
    return = MyTrans . lift . return 
    m >>= f = MyTrans $ do x <- runMyTrans m 
          runMyTrans (f x) 

instance MonadTrans MyTrans where 
    lift m = MyTrans $ lift m 

instance MonadPlus m => MonadPlus (MyTrans m) where 
    mzero = MyTrans $ lift mzero 
    -- Attempt #1 (Only reveals the first element) 
    m `mplus` n = MyTrans $ (runMyTrans m) `mplus` (runMyTrans n) 
    -- Attempt #2 (Incomplete: see undefined statements) 
--  m `mplus` n = MyTrans $ 
--     lift $ do a <- runErrorT $ runMyTrans m 
--        b <- runErrorT $ runMyTrans n 
--        case a of 
--        Right r 1 
--        Left _ -> undefined 
--         -> case b of 
--          Left _ -> undefined 
--          Right t -> return r `mplus` return t 



type MyMonad = MyTrans [] 

x = return 1 :: MyMonad Int 
y = MyTrans $ throwError "Error" :: MyMonad Int 

z = x `mplus` y 

main = do 
    print $ (runErrorT $ runMyTrans z) -- should be [Right 1, Left "Error"] 
+3

줄 끝의 모든 공백 문자로 도대체 무엇이 다릅니 까? –

답변

4
instance MonadPlus m => MonadPlus (MyTrans m a) where 
    mzero = MyTrans (ErrorT mzero) 
    MyTrans (ErrorT m) `mplus` MyTrans (ErrorT n) = MyTrans (ErrorT (m `mplus` n)) 

주의 : 난 단지 이것이 당신이 요청한 동작을 가지고 있다는 것을 확인하고는 MonadPlus 법칙을 만족하는 것을 확인하지 않았습니다. 그것들 중 일부 또는 전부를 위반할 가능성이 있습니다! 자신의 책임하에 사용하십시오.