A newbie's proud first code
Mon, 05 Nov 2001 11:51:12 +0100
Lennart Augustsson suggests another version of the code of Luke Maurer
who wrote his first 3-liner in Haskell:
> > My only issue (and it is nitpicky) is that I don't really like having to
> > declare an extra function (euler') in the same scope as euler. I tried
> > playing with where clauses or let expressions, but I couldn't find a way to
> > make GHC happy without introducing a bunch of extra variables (since I'd
> > need new versions of the arguments to euler; in euler', I just used the same
> > names. Also, nested "where" doesn't work as I'd like it to.) Is there, in
> > fact, a more concise way to express what I'm doing?
> How about?
> euler :: (Num a) => (a -> a -> a) -> a -> a -> [a]
> euler f' dt f0 = euler' f0 0
> where euler' f t = f : euler' fnext (t + dt)
> where fnext = f + dt * (f' f t)
> -- Lennart
Before that Adrian Hey produced a 4-liner.
GENTLEMEN! What happened to you?! Why all of you are so incredibly wasteful?
Full three (or even four...) lines for just that?
Here you have a one-liner:
euler f' dt f0 = map snd (iterate (\(t,f)->(t+dt,f+dt*f' t f)) (0,f0) )
(The map snd () prefix is just to get rid of useless time sequence, but you
might find some use of it, especially if you want to plot the result.
Then the code is even shorter.)
You might think that I am a shameless obfuscator, but I really often code
like that, and with an adequate support of fold-like primitives which
facilitate the processing of lists representing arithmetic sequences, it
is possible to write even a one-liner for a Runge-Kutta solver,
not only Euler. Perhaps Luke Maurer might look up this never published paper:
or a slightly improved one in French, somewhere near.
Now, is it a good thing to empoison beginners with such stuff?
I wouldn't dare to give it to my students. But for people who are fascinated
by the genericity and the compactness of functional coding, and by the
self-bootstrapping lazy sequences -- why not?