考虑一下一些monad变压器堆栈

{-# LANGUAGE GeneralizedNewtypeDeriving #-}
...
newtype J = J { runJ :: ErrorT Foo (StateT Bar IO) a } deriving (Applicative, Functor, etc)

以及J中的一些功能:
peekNextQuux :: J Quux
peekNextQuux = ...

withJ :: J a -> IO (Either Foo a)
withJ = ...

然后我发现自己在J上下文中。我会写
f = withJ $ peekNextQuux >>= liftIO . print

现在我想在J上下文中的单独线程中窥视并打印队列
g = withJ . liftIO . forkIO . forever $ peekNextQuux >>= liftIO . print

这显然是行不通的。我想有办法解决这个简单的问题,只是想不通。

最佳答案

您希望它如何运作?单独的线程必须有权访问某些状态和错误处理,因为J包装了StateTErrorT。线程应该如何访问它?在新线程中更新状态时,是否也应该在旧线程中更改状态?当新线程引发异常时,旧线程应该停止吗?

它不起作用,因为StateTErrorT是纯monad转换器,所以我描述的行为无法实现。您必须将状态显式传递给新线程并在其中运行新状态monad才能使其工作:

g = withJ . ... $ do
  state <- get
  liftIO . forkIO $ do
    flip execStateT state . forever $ peekNextQuux >>= liftIO . print

09-25 18:37