【发布时间】:2013-12-22 04:16:59
【问题描述】:
在t IO a monad 中运行t (ErrorT String IO) a 类型的代码的最佳方法是什么?考虑下面的代码:
module Sample where
import System.IO
import Control.Monad.Reader
import Control.Monad.Error
type Env = String
inner :: ReaderT Env (ErrorT String IO) ()
inner = do
s <- ask
fail s
outer :: ReaderT Env IO ()
outer = do
env <- ask
res <- lift $ runErrorT $ runReaderT inner env
case res of
Left err -> liftIO $ hPutStrLn stderr err
Right _ -> return ()
outer
这可行,但我一直在寻找一种更优雅的方式在我的堆栈底部插入 ErrorT。特别是我在我的项目中使用了几个不同的 monad 转换器堆栈,并且为每个堆栈编写上面的内容非常乏味。
我正在寻找类似的东西:
outer :: ReaderT Env IO ()
outer = do
res <- (hoist runErrorT) inner
...
但由于类型不匹配,我无法使用hoist。
编辑:
我在一些堆栈中使用StateT,这就是尝试将ErrorT 放在底部而不是顶部的原因。
outer 应该是一个无限循环。
【问题讨论】:
-
外部真的应该是无限循环吗?
-
@GaneshSittampalam 为什么不呢? Haskell 很懒,所以
runReaderT会产生一个有用的IO动作 -
IO 操作可能很有用,因为它在每次迭代或类似情况下都会与用户交互 - 只是我从问题中认为外部应该类似于内部但删除了 ErrorT 字符串。
标签: haskell error-handling monads monad-transformers