The MVar request–response pattern connects a requester to a service running in another thread. A pair of MVars forms a channel: one holds a request and the other returns its result. It gives actors an explicit communication boundary instead of direct access to one another’s internals. section 8.1.2 section 8.1.3
Figure 8.5 The MVar Request–Response pattern flow
The flow shows the reciprocal blocking that coordinates one requester and one responder: send a request, process it, then return a response. section 8.1.3
Use the channel as a small synchronous remote service:
- The requester puts a value into the request MVar, then takes the matching result from the response MVar. section 8.1.3
- The responder takes a request, computes its result, and puts that result into the response MVar before serving the next request. section 8.1.3
- Pair every takeMVar with a later putMVar; an unfilled MVar can leave another thread blocked indefinitely. section 8.1.3
FizzBuzz worker
A generic Pipe bundles request and response MVars. sendRequest puts an integer and waits; a worker repeatedly takes integers, applies FizzBuzz, and puts back strings. The same shape can carry typed request constructors, such as simulation commands, with a response MVar stored inside the request that requires a matching result type. section 8.1.3 section 8.2.1
For a simulator actor, embedding the response MVar in a request constructor makes completion part of handling that request. A finite RunSimulation returns a result, while StartSimulation launches ongoing work without one. This protocol can later be translated to a process boundary such as HTTP or gRPC. section 8.2.1
The pattern is useful for small, orderly thread interactions, but large MVar-based concurrent models can become awkward and overcomplicated. When that happens, STM or a message queue may better fit the architecture. section 8.3
