throwE 和 catchE 以及 exceptT monad 位于 Monadic 堆栈的底部

sho*_*qie 3 monads haskell exception monad-transformers

假设我有一个像这样的单子堆栈:

import Control.Monad.Trans.Reader
import Control.Monad.Trans.Except
import Control.Monad.Trans

type MyMonad = ReaderT Env (ExceptT String IO) -- Env is irrelevant
Run Code Online (Sandbox Code Playgroud)

和一个函数(简化,但想法成立):

f :: Integer -> MyMonad Integer
f 42 = lift $ throwE "42 is an ILLEGAL number"
f n = return n
Run Code Online (Sandbox Code Playgroud)

我现在想做的是f从另一个函数调用,但如果发生则捕获抛出的异常并以某种方式处理它(例如,抛出另一个异常但消息已更改)。我很难弄清楚应该在这里进行什么样的电梯操作才能正确完成。我尝试过这样的事情:

g n = do
  x <- (f n) `catchE'` (\_ -> lift $ throwE "nope, still illegal")
  return x
where catchE' - lift . catchE
Run Code Online (Sandbox Code Playgroud)

但它显然行不通,因为catchE'在 monad 中需要一些东西ExceptT,而不是MyMonad. 可以轻松完成吗?也许改变 monad 堆栈的结构会有帮助?

Li-*_*Xia 5

lift您需要的不仅仅是catch通过 monad 变压器。事实上,有些变压器根本无法升降catch(例如ContT)。然而,确实ReaderT有,而且最简单的利用方法是通过Control.Monad.Error.catchErrormtl 库。

  • 好吧,我明白了。`fn \`catchError\` (\_ -&gt; throwError "NOPE")` 按预期工作。谢谢你! (2认同)