管道monad而Just_ issue

时间:2013-06-20 02:56:21

标签: haskell monads conduit

考虑使用Lens,Conduit和Monad-Loops的以下Haskell代码:

type Broadcast = Int
type BroadcastChan = TChan Broadcast

data SessionState = SessionState
  { _broadcastChan :: BroadcastChan
  }

makeLenses ''SessionState

type Session m = StateT SessionState m
type SessionIO = Session IO

-- This function requires the state and IO...
processBroadcast :: Broadcast -> Conduit Broadcast SessionIO Packet
processBroadcast = undefined

-- | Handles networking
protocol :: Conduit Packet SessionIO Packet
protocol = do
  ch <- lift $ use broadcastChan
  -- line 51:
  whileJust_ (liftIO . atomically $ tryReadTChan ch) (\x -> yield $ processBroadcast x)
  liftIO $ putStrLn "End"

我无法通过大量的提升来解决以下类型错误:

src\Burrito\Network.hs:51:61:
    Couldn't match expected type `Packet'
                with actual type `Conduit Broadcast SessionIO Packet'
    Expected type: ConduitM Packet Packet SessionIO b0
      Actual type: ConduitM
                     Packet (Conduit Broadcast SessionIO Packet) m0 ()
    In the expression: yield $ processBroadcast x
    In the second argument of `whileJust_', namely
      `(\ x -> yield $ processBroadcast x)'

一些指导或建议将不胜感激。请记住,processBroadcast要求Session处理状态以进行处理。


1 个答案:

答案 0 :(得分:2)

这有效:

import Control
type Broadcast = Int
type BroadcastChan = TChan Broadcast

data SessionState = SessionState
  { _broadcastChan :: BroadcastChan
  }

makeLenses ''SessionState

type Session m = StateT SessionState m
type SessionIO = Session IO

-- This function requires the state and IO...
processBroadcast :: Broadcast -> Conduit a SessionIO Packet
processBroadcast b = undefined

-- | Handles networking
protocol :: Conduit Packet SessionIO Packet
protocol = do
  ch <- lift $ use broadcastChan
  -- line 51:
  whileJust_ (liftIO . atomically $ tryReadTChan ch) processBroadcast
  liftIO $ putStrLn "End"

由于函数processBroadcast只处理单个广播(我假设),因此无需将管道的输入类型限制为Broadcast。为了在协议中使用它,该管道的输入类型必须与协议Conduit的输入类型匹配,这是协议,因此在协议中,将processBroadcast中的a实例化为Packet。