Cartesian product on a list of lists in Haskell

Given a list of length lists x, where all the sublist letters are the same length y, print y^xlists of length xthat contain one item from each sublist.

Example ( x = 3, y = 2):

[ [1, 2], [3, 4], [5, 6] ]

Output ( 2^3 == 8different outputs):

[ [1, 3, 5], [1, 4, 5], [1, 3, 6], [1, 4, 6],
  [2, 3, 5], [2, 4, 5], [2, 3, 6], [2, 4, 6] ]

My research / work

ruby

I wrote the actual code to complete this task, but in Ruby, as it is the most convenient language for me.

def all_combinations(lst)
   lst.inject {|acc, new| acc.product(new).map(&:flatten) }
end

A type

Input is a list of lists containing elements of type a, etc. - output.

allProduct :: [[a]] -> [[a]]

Cartesian product, flattening and folding

Ruby, , . , , .

+4
1

: Haskell. *.lhs GHCi.

> -- remove this line if you don't have QuickCheck installed
> import Test.QuickCheck 

allProduct:

> allProductFirst :: [[a]] -> [[a]]
> allProductFirst []     = [[]]
> allProductFirst (x:xs) =

x . , allProduct xs .

>    let rest = allProductFirst xs

? x :

>    in concatMap (\k -> map (k:) rest) x

, 100% , allProduct [] - [[]].

, Monad []?

do

> allProduct' :: [[a]] -> [[a]]
> allProduct' []     = [[]]
> allProduct' (x:xs) = do

x

>      elementOfX <- x

, :

>      rest       <- allProduct' xs
>      return $ elementOfX : rest

, . : sequence :: Monad m => [m a] -> m [a]. m ~ [], sequence :: [[a]] -> [[a]].

sequence

:

> allProduct :: [[a]] -> [[a]]
> allProduct = sequence

QuickCheck , , , , allProductFirst allProduct':

> main :: IO ()
> main = do
>   quickCheck $
>     forAll (choose (1,8)) $ \n -> -- number of lists
>     forAll (choose (1,4)) $ \s -> -- number of elements per list
>     forAll (vectorOf n $ vector s) $ \xs ->
>       allProduct'     xs === allProduct (xs :: [[Integer]]) .&.
>       allProductFirst xs === allProduct xs

:main GHCi, runhaskell , 100 .

+13

Source: https://habr.com/ru/post/1606564/


All Articles