Скажем, у меня есть монадический стек, подобный этому:
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
.Это можно сделать легко?Возможно, поможет изменение структуры стека монад?