[Haskell-cafe] Generalizing nested list comprehensions
Daniel Fischer
daniel.is.fischer at web.de
Fri Feb 26 10:13:24 EST 2010
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
More information about the Haskell-Cafe
mailing list