I am curious if it is possible to dynamically build a list comprehension in Haskell.
As an example, if I have the following:
all_pows (a,a') (b,b') = [ a^y * b^z | y <- take a' [0..], z <- take b' [0..] ]
I get what I am after
*Main> List.sort $ all_pows (2,3) (5,3)
[1,2,4,5,10,20,25,50,100]
However, what I’d really like is to have something like
all_pows [(Int,Int)] -> [Integer]
So that I can support N pairs of arguments without building N versions of all_pows. I’m still pretty new to Haskell so I may have overlooked something obvious. Is this even possible?
The magic of the list monad:
This probably deserves a bit more explanation.
You could have written your own
such that
cartesianProduct [[1],[2,3],[4,5,6]]⇒[[1,2,4],[1,2,5],[1,2,6],[1,3,4],[1,3,5],[1,3,6]].However, comprehensions and monads are intentionally similar. The standard Prelude has
sequence :: Monad m => [m a] -> m [a], and whenmis the list monad[], it actually does exactly what we wrote above.As another shortcut,
mapM :: Monad m => (a -> m b) -> [a] -> m [b]is simply a composition ofsequenceandmap.For each inner list of varying powers of each base, you want to multiply them to a single number. You could write this recursively
or using a fold
but actually,
product :: Num a => [a] -> ais already defined! I love this language ☺☺☺