Ran across the homepage of Berkeley Logo a few days ago. One of the things on there is this demo code
to choices :menu [:sofar []] if emptyp :menu [print :sofar stop] foreach first :menu [(choices butfirst :menu sentence :sofar ?)] end
When invoked as
choices [[small medium large] [vanilla [ultra chocolate] lychee [rum raisin] ginger] [cone cup]]we get a list of choices starting with
small vanilla cone small vanilla cup small ultra chocolate cone small ultra chocolate cup …I got curious about how Haskell stacks up against Logo here… After a whole bunch of fiddling around with various versions I ended up with this
choices = foldr (\c cs -> [e : es | e <- c, es <- cs]) [[]]which when invoked as
choices [["small", "medium", "large"], ["vanilla", "ultra chocolate", "lychee", "rum raisin", "ginger"], ["cone", "cup"]]prints a list of choices that starts
[["small","vanilla","cone"],["small","vanilla","cup"] …
I have deliberately left the "ugly" input and output of the Haskell. One can paper around it, but I wanted to stress that the Haskell choices
, unlike the Logo version, is a generic combinator that returns its lists rather than printing them, so that they can be further processed; for example
map sum $ choices [[1, 2], [3, 4]]yields the list
[4, 5, 5, 6]
The other important point about the Haskell version is the lack of any kind of explicit iteration or recursion. This is of course not because Haskell has special operators for this case, but because Haskell's general-purpose operators normally allow one to avoid recursion or iteration—here it is wrapped up by the foldr
and by the list comprehension.
As I noted earlier, by extending our code from a one-liner to a two-liner we can get pretty output:
prettyChoices = putStr . unlines . map unwords . choicesAgain, there's no recursion here, just applying a series of transformations to the list of choices until it's a Haskell string and then printing that string.
I like Haskell a lot. I'm seriously considering teaching it to my boy. I'm working on a tutorial to that effect; I talked with a lot of folks about it at Open Source Bridge a week or more ago. This code snippet is something I think my boy may be able to learn to write if he gets interested. I'll be curious to find out. (B)