3

とりわけ、基本モナドにエラー機能を付与するモナド変換子を定義したいと思います。変換されたモナドは、ベース モナドが MonadPlus のインスタンスである必要がありますが、MonadPlus インスタンスを定義して、ErrorT トランスフォーマーが複数の回答を返すようにする方法がわかりません (複数の回答がある場合)。私の 2 つの試みは、以下のコードにあります。コードの最後には、ベース モナドが の場合にモナド変換子がどのように動作するかを示すステートメントがあり[]ます。ありがとう。

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"] 
4

1 に答える 1

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法律を満たしていることを確認していません. それらの一部またはすべてに違反している可能性は十分にあります。自己責任。

于 2012-12-18T22:07:09.477 に答える