考虑以下代码(和错误):
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))
是怎么来的吗? 最佳答案
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 尝试通过使用
TChan a
和 m (TChan Broadcast)
来统一 a ~ TChan Broadcast
和 m ~ TChan
,但它失败了,因为 TChan
不是 MoandState
的实例。您已经可以看到 TChan (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)
关于Haskell:在使用镜头修改状态时重复 TChan 包装,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/17099881/