Question

Consider the following Haskell code utilizing Lens, Conduit and Monad-Loops:

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"

I've been unable to solve the following type error through copious amounts of lifting:

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)'

Some guidance or advice would be appreciated. Keep in mind that processBroadcast requires the state being carried by Session for its processing.


Was it helpful?

Solution

This works:

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"

As the function processBroadcast only processes a single broadcast (I assumed that), there is no need to limit the conduit's input type to Broadcast. For using it in protocol, the input type of that conduit must match the input type of the protocol Conduit, which is Packet, so in protocol, the a in processBroadcast is instantiated to Packet.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top