The "dispatcher" could just look at the "id" and then `send` the associated value to the appropriate mailbox. E.g:
-- suppose we have a function that gives us a mailbox from an ID
-- in your program you could just store them in some datastructure
-- and just look them up, instead of having 'mailboxForId'
mailboxForId :: Int -> Output a
dispatcher :: Consumer (Int, a) IO ()
dispatcher = loop
where loop = do
(id, value) <- await
alive <- liftIO . atomically $
send (mailboxForId id) value
when alive loop
Gabriel's suggestion would work better though if there's a lot of these workers, I think.