Skip to main content

7. Use with-pattern based component interfaces

· 2 min read

Status

Accepted

Context

The with pattern or bracket pattern is a functional programming idiom, a particular instance of Continuation-Passing Style, whereby one component that controls some resource that is consumed by another component of the system, is created via a function that takes as argument a function consuming the resource, instead of returning it. This pattern allows safe reclaiming of resources when the "wrapped" action terminates, whether normally or unexpectedly.

TODO "Tying the knot"

Decision

We use this pattern to provide interfaces to all active components, which exchange messages with other components of the system. A prototypical signature of such a component could be:

type Component m = inmsg -> m ()
type Callback m = outmsg -> m ()

withXXX :: Callback m -> (Component m -> m a) -> m a

Note that withXXX can also allocate resources in order to provide Component or use the Callback, e.g. fork threads which invoke Callback, but also make sure they are cleaned up.

Consequences

Components can be layered on top of another to provide additional behavior given the same interface. This also similar to "decorating" in the object-orientation world.

If the Component is agnostic about the messages it consumes/produces, it can be defined as a Contravariant functor and the Callback part as a (covariant) Functor. This makes it possible to use map and contramap operations to transform messages.