Warning: file_get_contents(/data/phpspider/zhask/data//catemap/0/search/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Haskell 使用逻辑monad在ExceptT引发异常时回溯_Haskell_Search_Alternative Functor_Monadplus - Fatal编程技术网

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