The best I've been able to come up with is
combinations [] = [[]]
combinations (xs:xss) = do
x <- xs
ys <- combinations xss
return $ x : ys
The way I derived this was I first converted the list comprehension into monadic code (which also meant dropping the concat
to get it to type check)
combinations (xs:xss) =
let yss = combinations xss
in do
x <- xs
map (x:) yss
Then I realized that map (x:) yss
is exactly fmap (x:) yss
, which is exactly yss >>= return . (x:)
, so I knew I could do
combinations (xs:xss) =
let yss = combinations xss
in do
x <- xs
ys <- yss
return $ x : ys
And then it can be inlined as
combinations (xs:xss) = do
x <- xs
ys <- combinations xss
return $ x : ys