gpt4 book ai didi

haskell - 在do部分中使用ErrorT转换器monad

转载 作者:行者123 更新时间:2023-12-03 07:49:50 24 4
gpt4 key购买 nike

我想在do部分中了解如何处理转换程序堆栈。它还与错误处理有关。

即,我将向您展示我的问题。
我有一些功能:

foo :: Int -> String -> IO (Either String (Value, Integer))
foo的主体在这里并不重要。
ef :: evalExpr :: Int -> String ->  IO (Either String (Value, Integer))

现在,
f :: Integer -> String -> StateT Integer (ReaderT Integer (ErrorT String IO)) ()
f i s = do
vl <- lift $ lift $ lift $ ef i s
....
return ()
ef可以调用throwError。它还可以返回 (Value, String)
我希望能够( ....)用Right值( (Value, String))做一些事情。但是,我做不到。这是我的永久问题。

想法如下:
ef称为 throwError时, foo应该传播相同的错误(所以 Left String)。毫不费力,当 ef返回 Right Value (so (Value, String))时,我想使用它,并在此基础上做出决定,什么应该返回 foo- throwError(Value, ())
我知道 fmap<*>
你能帮我吗 ?

最佳答案

功能:

ef :: Int -> String ->  IO (Either String (Value, Integer))

只能 throwError一个 IOException:
instance MonadError IOException IO where
throwError = ioError
catchError = catch

否则,它只是返回 IOEither String (Value, Integer)函数。

给定该函数,要对其值起作用,您需要在具有 IO的上下文中执行它,然后简单地使用结果值:
callEf :: IO ()
callEf = do
result <- ef ...
case result of
Left s -> -- do something with the String
Right (v, i) -> -- do something with the tuple

return ()
-- ^ you can also obviously produce the value above,
-- if you want something more complicated than ()

如果您位于monad堆栈中,则不会改变。在函数 f中,三次调用 lift将为您提供 IO上下文。之后,您可以对结果值进行任何所需的操作,包括堆栈中的任何操作,例如 throwError(两次提升后)或 put(不提升)。

另外,请引用我对上一个问题的回答,以摆脱 lift

如果您希望错误传播从 EitherErrorT自动发生,那将是相当简单的,就像上面这样:
eitherToError :: Either e v -> ErrorT e m v
eitherToError f = case f of
Left err -> throwError err
Right val -> return val

您可以 easily search for in Hayoo,在某些库中生成 in a very similar implementation

综上所述,似乎不赞成使用 ErrorT,而建议使用 Control.Monad.Trans.Except

关于haskell - 在do部分中使用ErrorT转换器monad,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36746135/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com