
On Tue, 2005-08-30 at 11:08 +0100, Bayley, Alistair wrote:
From: Martin Vlk [mailto:vlcak01@tiscali.cz]
http://www-i2.informatik.rwth-aachen.de/Staff/Current/michaelw/sttt-ml-haske ll.pdf
This quote from the paper resonated with me:
"Also, if imperative elements of a given application were not taken into account during its design but turn out to be necessary later on, often major parts have to be redesigned or (at least) reimplemented, especially because types change significantly. A simple but recurring example is to add printing of status information to an otherwise purely functional algorithm. In the worst case this could result in having to rewrite the algorithm in a monadic style, but also to rewrite its callers (and transitively their callers as well), plus adjusting all type annotations on the way. Even when using opaque accessors to data structures, the required changes cannot necessarily be limited to a single module, but affect large parts of the system."
This is often a misconception, that just because you find you need to 'do' something in the middle of your algorithm, that you need to convert it wholly to monadic style. In the above example, it sounds like a better approach might be to keep the algorithm pure but change it slightly so that it returns a list of intermediate results rather than just the final results. That way an outer bit of code in the IO monad can print status information, but the core of the algorithm remains pure. However such a trick is obviously not possible in every case, such as your example of converting some pure array code to use destructive update. (Unless you can make your code into a function from the current state of the array to the new state (perhaps by returning a list of changes) in which case you could partition the code into the pure part and a thin wrapper that does the iteration and actually updates a mutable array) Duncan