在Haskell中结合RWST与IO Monad后无法获取外层日志的问题
解决RWST结合IO时无法获取日志的问题
我瞅了下你的代码,发现两个核心问题导致你拿不到外层monad的日志,咱们一步步拆解解决:
1. 类型定义错误:日志容器被设为空值
你当前的VM2定义里,RWST的第二个类型参数(日志存储容器)是()——这是个空类型,根本没法存储任何日志内容!而你后面的run函数用的是RWST () [String] () IO (),说明你本来想把[String]作为日志类型,所以得先修正VM2的类型:
-- 把日志类型从()改成[String],同时派生MonadWriter等实例方便操作日志 newtype VM2 a = VM2{ unwrapVM :: RWST () [String] () IO a } deriving (Functor, Applicative, Monad, MonadIO, MonadReader (), MonadWriter [String], MonadState ())
2. 使用了错误的RWST运行函数:evalRWST会丢弃日志
你在runVmEval里用了evalRWST,这个函数的作用是只返回计算结果,直接丢弃状态和日志。要拿到日志,你得用runRWST,它会返回完整的三元组(计算结果, 最终状态, 生成的日志):
runVmEval :: VM2 a -> IO () runVmEval m = do -- 用runRWST替代evalRWST,获取完整的计算结果、状态和日志 (_, _, logs) <- runRWST (unwrapVM m) () () -- 遍历打印所有日志 mapM_ putStrLn logs putStrLn "End"
测试修正后的代码
现在你可以在VM2里用tell函数写入日志,同时正常执行IO操作:
test :: IO () test = do putStrLn "Start" runVmEval $ do -- 写入第一条日志 tell ["日志1:VM初始化完成"] -- 执行IO操作 liftIO $ putStrLn "正在执行IO任务..." -- 写入第二条日志 tell ["日志2:IO任务执行完毕"]
运行这个test函数,你就能看到日志被正确打印出来了。
内容的提问来源于stack exchange,提问作者Eddtothefullest
相关产品推荐
相关产品推荐

