[Haskell-cafe] Writer + log each computation to stdout

oleg at okmij.org oleg at okmij.org
Tue Nov 26 10:25:17 UTC 2013

Bryan Vicknair wrote:

> I have a bunch of little database IO functions.  Each does something to the
> database, and returns a log string describing what it did, and possibly a
> meaningful result from the database.
> ...and a few functions that orchestrate all the little functions into doing
> useful work.
> I don't want the individual functions to know what is done with the log string
> describing what they did.  Top-level orchestrating functions should make that
> decision, which can be one of:
> 1) Collect and print all to a log once all computations are done.
> 2) Print to stdout *as each computation is run*.
> 3) Ignore them.

What an excellent case for extensible effects! Many thanks to Ben
Foppa for making the package available on hackage, as

Extensible Effects designed specifically to separate a client (the
requestor of an action) from a handler, the executor of an action. A
logging client merely requests a string to be logged. It has no idea
what happens when that request is executed. Therefore, the same
client can be used with several handlers, even within the same
expression.  One can also build various interceptors, such as
logIntercept, which is similar to Unix' tee.

The following file illustrates how to solve the problem with all three
The extensible effects package actually defines a very similar
function, calls trace.  For illustration and clarity, the file
develops the Logging effect from scratch. After all, Extensible
Effects encourages developing effects to suit the problem at
hand. Defining a new effect is as simple as

-- The request to log a string
-- The request carries the String to log. It seems no particular
-- reply is needed for the request (other than the simple acknowledgment),
-- so we set the reply to be unit.
data Log v = Log String (() -> v)
    deriving (Typeable, Functor)

Clients use the function

        logit :: Member Log r => [Char] -> Eff r ()

(this signature, as all signatures in the code, are inferred). The
signature says that the function request Log effect to be done. It
does not concern itself how this effect its to be done.
The file shows three handlers: runLogCollect, runLogTrace,
runLogIgnore. There is also another handler, logIntercept, that like 
Unix 'tee', prints out the log message immediately while still
propagating it. It can be used with any of the three handlers.

More information about the Haskell-Cafe mailing list