Calculate n-ary Cartesian Product

后端 未结 6 2124
别跟我提以往
别跟我提以往 2020-12-16 18:03

Given two lists, I can produce a list of all permutations the Cartesian Product of these two lists:

permute :: [a] -> [a] -> [[a]]
per         


        
相关标签:
6条回答
  • 2020-12-16 18:18

    If you want to have more control over the output, you can use a list as applicative functor, e.g.:

    (\x y z -> [x,y,­z]) <$>  [1,2]­ <*> [4,5]­ <*> [6,7]
    

    Let's say you want a list of tuples instead:

    (\x y z -> (x,y,­z)) <$>  [1,2]­ <*> [4,5]­ <*> [6,7]
    

    And it looks kind of cool, too...

    0 讨论(0)
  • 2020-12-16 18:23
    Prelude> sequence [[1,2],[3,4],[5,6]]
    [[1,3,5],[1,3,6],[1,4,5],[1,4,6],[2,3,5],[2,3,6],[2,4,5],[2,4,6]]
    
    0 讨论(0)
  • 2020-12-16 18:23

    As a supplement to jleedev's answer (couldn't format this in the comments):

    A quick unchecked substitution of list functions for monadic ones:

    sequence ms = foldr k (return []) ms
       where
        k m m' = do { x <- m; xs <- m'; return (x:xs) }
    

    ....

        k m m' = m >>= \x -> m' >>= \xs -> [x:xs]
        k m m' = flip concatMap m $ \x -> flip concatMap m' $ \xs -> [x:xs]
        k m m' = concatMap (\x -> concatMap (\xs -> [x:xs]) m') m
    

    ....

    sequence ms = foldr k ([[]]) ms
       where
         k m m' = concatMap (\x -> concatMap (\xs -> [x:xs]) m') m
    
    0 讨论(0)
  • 2020-12-16 18:24

    Here is my way of implementing it simply, using only list comprehensions.

    crossProduct :: [[a]] -> [[a]]
    crossProduct (axis:[]) = [ [v] | v <- axis ]
    crossProduct (axis:rest) = [ v:r | v <- axis, r <- crossProduct rest ]
    
    0 讨论(0)
  • 2020-12-16 18:26

    I found Eric Lippert's article on computing Cartesian product with LINQ quite helpful in improving my understanding of what was going on. Here's a more-or-less direct translation:

    cartesianProduct :: [[a]] -> [[a]]
    cartesianProduct sequences = foldr aggregator [[]] sequences
                       where aggregator sequence accumulator = 
                             [ item:accseq |item <- sequence, accseq <- accumulator ]
    

    Or with more "Haskell-y" terse, meaningless parameter names ;)

    cartesianProduct = foldr f [[]]
                        where f l a = [ x:xs | x <- l, xs <- a ]
    

    This winds up being quite similar to sclv posted after all.

    0 讨论(0)
  • 2020-12-16 18:28

    You can do that in 2 ways:

    1. Using list comprehension

    cp :: [[a]] -> [[a]]

    cp [] = [[]]

    cp (xs:xss) = [ x:ys | x <- xs, ys <- cp xss ]

    1. Using a fold

    cp1 :: [[a]] -> [[a]]

    cp1 xs = foldr f [[]] xs

      where f xs xss = [x:ys | x <- xs, ys <- xss]
    
    0 讨论(0)
提交回复
热议问题