
On Thu, 2009-06-18 at 23:57 +0800, Lee Duhem wrote:
[...] I have prepared a blog post for how I worked out some of these answers, here is the draft of it, I hope it can help you too.
Nice post! Certainly, pen-and-paper reasoning like this is a very good way to develop deeper intuitions.
Answer 1 (by Matthew Brecknell):
concat $ tail $ iterate (map (:) ['a' .. 'z'] <*>) [[]]
I actually said "tail $ concat $ iterate ...", because I think the initial empty string is logically part of the sequence. Tacking "tail" on the front then produces the subsequence requested by the OP. I should have given more credit to Reid for this solution. I'm always delighted to see people using monadic combinators (like replicateM) in the list monad, because I so rarely think to use them this way. Sadly, my understanding of these combinators is still somewhat stuck in IO, where I first learned them. I never would have thought to use <*> this way if I had not seen Reid's solution first. Also, for many applications, a non-sharing version like Reid's is really what you want. Sharing versions have to keep references to old strings around to reuse later, and so are really only appropriate for applications which would keep them in memory anyway. Regards, Matthew