Haskell:TChan包装复制,同时使用镜头修改状态

时间:2013-06-14 01:43:13

标签: haskell stm lenses

考虑以下代码(和错误):

import Control.Lens
import Control.Monad.STM
import Control.Monad.IO.Class
import Control.Monad.State.Lazy
import Control.Concurrent.STM.TChan

data Broadcast = Broadcast Int

data ImmutableState = ImmutableState
    { _broadcastChan :: TChan Broadcast
    , _encryption    :: Int
    }

makeLenses ''ImmutableState

helper :: MonadIO m => StateT ImmutableState m a
helper = do
    broadcastChan <~ (liftIO . atomically $ dupTChan $ use broadcastChan)
    {- ^
        Test.hs:
            Couldn't match expected type `Broadcast'
                        with actual type `TChan Broadcast'
            Expected type: StateT ImmutableState m (TChan Broadcast)
              Actual type: StateT ImmutableState m (TChan (TChan Broadcast))
            In the second argument of `(<~)', namely
              `(liftIO . atomically $ dupTChan $ use broadcastChan)'
            In a stmt of a 'do' block:
              broadcastChan
              <~ (liftIO . atomically $ dupTChan $ use broadcastChan)
    -}

forkImmState :: MonadIO m => ImmutableState -> m ImmutableState
forkImmState s = evalStateT helper s

有人可以解释(TChan (TChan Broadcast))是如何形成的吗?

1 个答案:

答案 0 :(得分:2)

dupTChan期望像[{1}}这样的论点,并且正在应用类似TChan a的内容。如果你直接尝试,你会得到一种稍微不同的类型错误

MonadState ImmutableState m => m (TChan Broadcast)

GHC尝试通过*Main> :t dupTChan $ use broadcastChan <interactive>:1:12: No instance for (MonadState ImmutableState TChan) arising from a use of `use' Possible fix: add an instance declaration for (MonadState ImmutableState TChan) In the second argument of `($)', namely `use broadcastChan' In the expression: dupTChan $ use broadcastChan TChan a来统一m (TChan Broadcast)a ~ TChan Broadcast,但失败是因为m ~ TChan不是TChan的实例1}}。您已经可以看到MoandState错误是如何形成的,但它无法统一,因此它会停止。

只有当我们声称我们知道结果的类型时,GHC会告诉我们它在幕后尝试的内容

TChan (TChan Broadcast)