1

考虑以下使用 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 携带的状态进行处理。


4

1 回答 1

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 仅处理单个广播(我假设),因此无需将管道的输入类型限制为广播。为了在协议中使用它,该管道的输入类型必须与协议Conduit的输入类型匹配,即Packet,因此在协议中,processBroadcast中的a被实例化为Packet。

于 2013-06-20T04:56:00.200 回答