4

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

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))是怎么回事吗?

4

1 回答 1

2

dupTChan期待一个类似的论点TChan a,并且正在应用类似的东西MonadState ImmutableState m => m (TChan Broadcast)。如果你直接尝试,你会得到一种稍微不同的类型错误

*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

GHC 试图通过拥有and来统一TChan aand ,但它失败了,因为它不是. 您已经可以看到错误是如何形成的,但它无法统一,所以它停止了。m (TChan Broadcast)a ~ TChan Broadcastm ~ TChanTChanMoandStateTChan (TChan Broadcast)

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

*Main> :t (dupTChan $ use broadcastChan) :: STM (TChan Broadcast)

<interactive>:1:2:
    Couldn't match type `TChan Broadcast' with `Broadcast'
    Expected type: STM (TChan Broadcast)
      Actual type: STM (TChan (TChan Broadcast))
    In the expression:
        (dupTChan $ use broadcastChan) :: STM (TChan Broadcast)
于 2013-06-14T04:43:54.850 回答