Haskell 使用逻辑monad在ExceptT引发异常时回溯
我想使用Haskell 使用逻辑monad在ExceptT引发异常时回溯,haskell,search,alternative-functor,monadplus,Haskell,Search,Alternative Functor,Monadplus,我想使用逻辑monad来确保抛出错误的代码(在monad堆栈中,包括除了)在抛出错误时返回。下面是一个简单的例子: newtype FooT m a = FooT { unFooT :: ExceptT String m a } deriving (Functor, Applicative, Monad, MonadTrans, MonadError String, MonadFail) foo :: FooT Logic String foo = do let validate
逻辑
monad来确保抛出错误的代码(在monad堆栈中,包括除了
)在抛出错误时返回。下面是一个简单的例子:
newtype FooT m a = FooT { unFooT :: ExceptT String m a }
deriving (Functor, Applicative, Monad, MonadTrans, MonadError String, MonadFail)
foo :: FooT Logic String
foo = do
let validate s = if s == "cf" then return s else throwError "err"
let go = do
first <- msum (map return ['a', 'b', 'c'])
second <- msum (map return ['d', 'e', 'f'])
traceM $ "Guess: " ++ [first, second]
validate [first, second]
go `catchError` const mzero
testfoo :: IO ()
testfoo = do
let r = observe $ runExceptT $ unFooT foo
case r of
Left e -> print $ "Error: " ++ e
Right s -> print $ "Result: " ++
同样的代码也适用于备选方案
实例。然而,这实际上没有帮助;它仍然没有回溯。这个例子有什么问题吗?有没有更好的办法来解决这个问题?我是不是在试图做一些毫无意义的事情?在一天结束的时候,我总是可以把所有的东西都抬起来,但我宁愿避免这样做
编辑:
我又在胡闹了。如果我使用
mplus
我上面的MonadPlus
实例可以工作,但是如果我像上面那样使用msum
则无法工作…使用MonadPlus
/的此实例替代方案
:
实例(可选m,单子m)=>可选(英尺m)其中
空=英尺(空除外)
英尺(a除外)英尺(b除外)=英尺(a除外)
注意:Alternative
和MonadPlus
是冗余的,因此只需实现Alternative
,并使用Data.Foldable.asum
而不是msum
您实现的示例与已在ExceptT
上的示例没有太大区别,并且没有真正使用备选m
实例。确保使用专用于m
的()
从回溯中获益
instance MonadPlus m => MonadPlus (FooT m) where
mzero = lift mzero
mplus (FooT a) (FooT b) = lift $ do
ea <- runExceptT a
case ea of
Left _ -> do
eb <- runExceptT b
case eb of
Left _ -> mzero
Right y -> return y
Right x -> do
eb <- runExceptT b
case eb of
Left _ -> return x
Right y -> return x `mplus` return y