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 堆栈的结构会有帮助?
lift您需要的不仅仅是catch通过 monad 变压器。事实上,有些变压器根本无法升降catch(例如ContT)。然而,确实ReaderT有,而且最简单的利用方法是通过Control.Monad.Error.catchErrormtl 库。