throwE和catchE与monadic堆栈底部的ExceptT monad

问题描述 投票:1回答:1

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

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 monad中采取了一些东西,而不是MyMonad。可以轻松完成吗?也许改变monad堆栈的结构可能会有所帮助?

haskell exception monads monad-transformers
1个回答
3
投票

你需要的不仅仅是lift通过monad变压器提升catch。事实上,有些变形金刚根本无法解除catch(例如ContT)。然而,对于ReaderT来说,最简单的方法是通过mtl库中的Control.Monad.Error.catchError

© www.soinside.com 2019 - 2024. All rights reserved.