quux (['0'..9'] ++ ['A'..F']) 2 generates hexademical numbers of length 2 (with leading zeros), but it's obviously possible to generate any base and any length.

quux digits length = iterate foo return !! length $ [] where  
    foo bb aa = map (: aa) digits >>= bb

Can this code be simplified, while retaining the idea of iterating in list monad?

  • \$\begingroup\$ Is this just replicateM, except specialized to lists? \$\endgroup\$
    – Carl
    Nov 28 '14 at 6:33
  • \$\begingroup\$ flip replicateM :) you can put it as an answer. \$\endgroup\$
    – nponeccop
    Nov 28 '14 at 10:59

It turns out that this is exactly what replicateM does in the [] monad. For the sake of completeness, let's look at exactly how replicateM works.

replicateM :: Monad m => Int -> m a -> m [a]
replicateM n x = sequence (replicate n x)

replicate :: Int -> a -> [a]
replicate n x = [ x | _ <- [1..n] ]

replicateM turns out to just pass off the heavy lifting to replicate and sequence. replicate is pretty simple, so the interesting part happens in sequence:

sequence :: Monad m => [m a] -> m [a]
sequence [] = return []
sequence (x:xs) = do
    x'  <- x
    xs' <- sequence xs
    return (x' : xs')

And in fact, that's exactly what leaning on the [] monad instance for iteration looks like. A couple of binds and a return.


Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.