2013-06-14 6 views
4

Рассмотрим следующий код (и ошибок):Haskell: TChan обертывание дублироваться при использовании объектива, чтобы изменить состояние

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)) приходит быть?

ответ

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 пытается объединить 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)