考虑以下代码(和错误):
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))
是如何形成的吗?
答案 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)