在Monadic堆栈底部使用ExceptT monad进行throwE和catchE

时间:2019-04-26 19:31:40

标签: haskell exception monads 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

还有一个函数(简化了,但是这个想法成立了):

f :: Integer -> MyMonad Integer
f 42 = lift $ throwE "42 is an ILLEGAL number"
f n = return n

我现在想做的是从另一个函数调用f,但是如果发生了抛出的异常并以某种方式对其进行了处理(例如,抛出另一个异常,但是消息已更改)。我很难确定在这里应该执行哪种举升操作才能正确完成。我尝试过这样的事情:

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

,但是显然不起作用,因为catchE'ExceptT单子而不是MyMonad取某物。能容易做到吗?也许更改monad堆栈的结构可能会有所帮助?

1 个答案:

答案 0 :(得分:3)

您需要超过lift才能通过单声道变压器提升catch。实际上,有些变压器根本无法举起catch(例如ContT)。但是对于ReaderT来说,存在,最简单的使用方法是通过mtl库中的Control.Monad.Error.catchError