Generalizing nested list comprehensions

Hi all, If this question sounds a bit noob-ish, that would be because I am one - so apologies in advance! I have functions that look something like these: f1 :: [a] -> [b] f1 xs = [foo [x1, x2] | x1 <- xs, x2 <- bar x1, baz x1 /= baz x2] f2 :: [a] -> [b] f2 xs = [foo [x1, x2, x3] | x1 <- xs, x2 <- bar x1, x3 <- bar x2, baz x1 /= baz x2, baz x1 /= baz x3, baz x2 /= baz x3] f3 :: [a] -> [b] f3 xs = [foo [x1, x2, x3, x4] | x1 <- xs, x2 <- bar x1, x3 <- bar x2, x4 <- bar x3, baz x1 /= baz x2, baz x1 /= baz x3, baz x1 /= baz x4, baz x2 /= baz x3, baz x1 /= baz x4] Note that for the purposes of this discussion it does not matter what foo, bar and baz do. Now what I want to do is write a generalized function fn based on the pattern set by f1, f2 and f3 such that: fn :: Int -> [a] -> [b] and: (fn 1 xs) == f1 xs (fn 2 xs) == f2 xs (fn 3 xs) == f3 xs (fn 25 xs) == f25 xs - obviously if I were to implement f25 as nested list comprehensions it would be ridiculously tedious! Any ideas how I can implement fn? Thanks, Ishaaq -- View this message in context: http://old.nabble.com/Generalizing-nested-list-comprehensions-tp27719199p277... Sent from the Haskell - Haskell-Cafe mailing list archive at Nabble.com.

Am Freitag 26 Februar 2010 15:52:15 schrieb Ishaaq Chandy:
Hi all, If this question sounds a bit noob-ish, that would be because I am one - so apologies in advance!
I have functions that look something like these:
f1 :: [a] -> [b] f1 xs = [foo [x1, x2] | x1 <- xs, x2 <- bar x1, baz x1 /= baz x2]
f2 :: [a] -> [b] f2 xs = [foo [x1, x2, x3] | x1 <- xs, x2 <- bar x1, x3 <- bar x2, baz x1 /= baz x2, baz x1 /= baz x3, baz x2 /= baz x3]
f3 :: [a] -> [b] f3 xs = [foo [x1, x2, x3, x4] | x1 <- xs, x2 <- bar x1, x3 <- bar x2, x4 <- bar x3, baz x1 /= baz x2, baz x1 /= baz x3, baz x1 /= baz x4, baz x2 /= baz x3, baz x1 /= baz x4]
Note that for the purposes of this discussion it does not matter what foo, bar and baz do.
Now what I want to do is write a generalized function fn based on the pattern set by f1, f2 and f3 such that: fn :: Int -> [a] -> [b] and: (fn 1 xs) == f1 xs (fn 2 xs) == f2 xs (fn 3 xs) == f3 xs (fn 25 xs) == f25 xs
- obviously if I were to implement f25 as nested list comprehensions it would be ridiculously tedious!
Any ideas how I can implement fn?
The easy way is recursion: import Control.Monad (guard) fn n xs = do x1 <- xs let b1 = baz x1 contFn n [] [b1] x1 contFn 0 acc _ xn = [foo (reverse (xn:acc)] contFn n acc bs xi = do xj <- bar xi let bj = baz xj guard (all (/= bj) bs) contFn (n-1) (xi:acc) (bj:bs) xj Now, there is probably a frighteningly elegant way to do it with foldM or somesuch, but I don't see it at the moment :(
Thanks, Ishaaq

Daniel Fischer wrote:
Ishaaq Chandy wrote:
If this question sounds a bit noob-ish, that would be because I am one - so apologies in advance!
I have functions that look something like these:
f1 :: [a] -> [b] f1 xs = [foo [x1, x2] | x1 <- xs, x2 <- bar x1, baz x1 /= baz x2]
f2 :: [a] -> [b] f2 xs = [foo [x1, x2, x3] | x1 <- xs, x2 <- bar x1, x3 <- bar x2, baz x1 /= baz x2, baz x1 /= baz x3, baz x2 /= baz x3] [...]
Now, there is probably a frighteningly elegant way to do it with foldM or somesuch, but I don't see it at the moment :(
That would be a variant of iterate for monads. iterateM :: Int -> (a -> m a) -> a -> m [a] iterateM n f a | n < 0 = return [] | otherwise = (a:) `liftM` (iterateM (n-1) f =<< f a) f n xs = filter p `liftM` (iterateM n bar =<< xs) where p xs = let ys = map baz xs in nub ys == ys Regards, Heinrich Apfelmus -- http://apfelmus.nfshost.com
participants (3)
-
Daniel Fischer
-
Heinrich Apfelmus
-
Ishaaq Chandy