FW: Haskell accumulator

Jon Fairbairn Jon.Fairbairn@cl.cam.ac.uk
Fri, 14 Jun 2002 12:33:07 +0100


> Paul Graham is collecting canonical accumulator generators at
> http://www.paulgraham.com/accgen.html , and has Dylan, E, JavaScript,
> various dialects Lisp, Lua, Rebol, Ruby, Perl, Python and Smalltalk.

As others have implied, the only correct answer to this is
"it's the wrong question".  One of the major advantages of
functional programming is that you do most things without
global variables, because they are a Bad Thing. So an
accumulator based on a variable is simply not the
appropriate abstraction in most cases.

Think about sum:

sum =3D foldl (+) 0

That works by using an accumulator, but Haskell is so
expressive you don't even need to mention the fact!

In addition the question is underspecified -- what happens,
for example if the argument isn't a number? This is not a
problem for Haskell, of course, but in allowing the lisp
version to throw an exeption he finesses away the advantage
of strong typing.

> Could the serious Haskellers comment on this attempt of mine?
> =

> foo n =3D do
>   n' <- newIORef n
>   return (\i -> do { modifyIORef n' (i+); readIORef n' })


What strikes me about this, though, is that perhaps the
imperative primitives in Haskell aren't quite perfectly
designed. It seems to me that modifyIORef ought to return
either the IORef of its value. In Algol68 if n IS a REF INT,
(n +:=3D i) has the value a (which will now contain it's
previous contents plus i), so it's a time honoured form.

If we had such a version (call it modIORef) we could dazzle
the blighters with:

foo n =3D fmap (\n' i -> modIORef n' (+i) >>=3D readIORef)
             $ newIORef n

and if we had one that returned the value (say modReadIORef)

foo n =3D fmap (\n' i -> modReadIORef n' (+i)) =

             $ newIORef n

Now, it was the work of moments to define and test (helped
by the type system) the above new functions, which shows
what expressive power is really about.

 J=F3n

PS It's perhaps a bit disappointing that one needs a type
signature to use

foo =3D fmap (\n' i->modReadIORef n'(+i)) . newIORef

-- =

J=F3n Fairbairn                                 Jon.Fairbairn@cl.cam.ac.u=
k