[Haskell-cafe] Annotating calculations
GK at ninebynine.org
Wed Jun 15 16:13:40 EDT 2005
At 18:48 15/06/05 +0200, Rene de Visser wrote:
>>From: Henning Thielemann <lemming at henning-thielemann.de>
>>On Wed, 15 Jun 2005, Rene de Visser wrote:
>> > I have a somewhat complicated calculation programmed in Haskell.
>> > This calculation is coded without using monads.
>> > I want to also produce a report describing the details of this calculation
>> > for each particular set of inputs.
>> > On the other hand replicating the calculation source code twice, once
>> > without reporting and once without seems bad.
>>smaller parts. If you have more breaks you have more chances to get
>>temporary results. You can put temporary values into a data structure.
>>E.g. if you have an iteration don't write a recursion with a fixed abort
>>criterion but write a function which maps the old value to the new one,
>>then apply 'iterate' on it. Now you can inspect the temporary values and
>>you can later apply a function which decides when to stop the iteration.
>Thankyou for the reply,
>The calculation is for the mostly already structured as you have suggested.
>The trouble is there are lots of little pieces that need to be put together.
>Do I need to put these pieces together twice? Once to put the whole
>And once to do the reporting? This is what I'd like to avoid.
>(A good deal of the complexity comes from that the calculation has a
>It would be nice to describe the structure once (at the moment the
>structure of the calculation is describe impliciitly in the Haskell
>functions) and use it both for the calculation and for the reporting.
I think your "instinct" that the structure of the calculation not be
repeated is sound. Furthermore, I think that Haskell is well suited to
avoiding such duplication.
Without knowing details of your problem it is difficult to be certain how
to proceed, but it seems to me that you maybe have some kind of structure
(or traversal pattern) over your data that can be separated from the
A starting point might be to separate the traversal from the computation,
and code the traversal as a higher order function (taking a parameter which
is a function that performs the data specific operations). If there are
many different internal data types, it might be worth considering using a
type class rather than a function parameter. (Or to go the whole hog, look
up the technique described in SPJ/Ralf Laemmel's Generic Haskell work --
look for "Scrap Your Boilerplate" -- but that may be more than you need.)
Staying with non-monadic functions, the computation and the formatting
could be handled as simple functions, where formatting returns something
like a StringS value, which can be output separately, but this might
require some creativity for the type of the traversal function.
Another approach would be to declare your basic traversal structure type as
an extended Functor that supports an fmapM function which allows a monadic
function to be applied over the structure "collecting" values in some way
-- this being used to collect or perform output. There's a thread about
this idea starting here:
Bear in mind that, with Haskell, you can design your algorithm as if it
generates an intermediate data structure without necessarily having to
store the entire structure in memory. So if you have a list of values,
each of which you require to subject to some transformation, followed by
another operation that (say) formats the list, then you could: (a) use
'map' to apply the transformation to each element, creating a new list,
then (b) use something like 'concatMap show' to format and concatenate the
values. Doing this, it appears you need space the intermediate list, but
lazy evaluation can mean that the entire list is never required all
together. In such cases, I tend to think of the intermediate list or data
structure as describing a traversal sequence or pattern, rather than as a
"concrete" data value.
I touch briefly on some of these issues in "Learning Haskell Notes":
More information about the Haskell-Cafe