
Patrick LeBoutillier
Sure. If you don't mind that the mutations come in a different order, one thing that works wonders is "sequence",
sequence :: Monad m => [m a] -> m [a]
In particular, for m = [], sequence :: [[a]] -> [[a]]. Then, knowing what sequence does, we can write
import Control.Monad (sequence)
generateAll :: String -> [String] generateAll word = sequence (map f word) where f c = case lookup c leat of Just r -> [c,r] Nothing -> [c]
That's very nice!
One question though: In the docs sequence is described as:
"Evaluate each action in the sequence from left to right, and collect the results."
How is one supposed to deduce what the behavior will be for the list monad (besides looking at the source)?
Intuitively it's very easy to understand and makes perfect sense, if you interpret the list monad as nondeterminism: sequence [c1,c2,c3] = do x1 <- c1 x2 <- c2 x3 <- c3 return [x1,x2,x3] sequence ["ab", "cd", "ef"] = do x1 <- "ab" x2 <- "cd" x3 <- "ef" return [x1,x2,x3] = ["ace", "acf", "ade", "adf", "bce", "bcf", "bde", "bdf"] In this code x1 stands for all results of c1, x2 for all results of c2 and x3 for all results of c3. It's a convenient way of doing list comprehension without syntactic sugar. See also mapM and replicateM, which have interesting behaviours in the list monad. Greets Ertugrul -- nightmare = unsafePerformIO (getWrongWife >>= sex) http://blog.ertes.de/