Search code examples
haskelllist-comprehension

How to combine two lists with list comprehension in Haskell?


I would like to combine two lists as with operator ++. [1,2,3] ++ [4,5,6] = [1,2,3,4,5,6]

So I tried this:

combine2 :: [a] -> [a] -> [a]
combine2 xs ys = [x : ys | x <- xs]

but that is giving me:

a.hs:10:19: error:
    • Occurs check: cannot construct the infinite type: a ~ [a]
    • In the expression: x : ys
      In the expression: [x : ys | x <- xs]
      In an equation for ‘combine2’: combine2 xs ys = [x : ys | x <- xs]
    • Relevant bindings include
        x :: a (bound at a.hs:10:28)
        ys :: [a] (bound at a.hs:10:13)
        xs :: [a] (bound at a.hs:10:10)
        combine2 :: [a] -> [a] -> [a] (bound at a.hs:10:1)
   |
10 | combine2 xs ys = [x : ys | x <- xs]

how to fix that?


Solution

  • The way to fix it is to make it more general. Instead of combine2, write combineN and use it so solve the combine2 problem.

    combine2 :: [b] -> [b] -> [b]
    combine2 xs ys = combineN [xs,ys]
    
    combineN :: [[b]] -> [b]
    combineN ls = [a | l <- ls, a <- l]
    

    We just draw each list from the argument list of lists, and then we draw and produce each element from each list, as if in the inner loop of the two nested loops. In pseudocode:

      for l in ls:
         for a in l:
             produce a
    

    Testing:

    > combine2 [1..3] [11..15]
    [1,2,3,11,12,13,14,15]
    
    --   l1:      l2:
    -- [ [1,2,3], [11,12,13,14,15] ]    -- outer "loop"
    -- [  1,2,3 ,  11,12,13,14,15  ]    -- inner "loop"
    

    Or we can see this as putting our lists one under the other in kind of ragged "matrix" and then reading it row by row, element by element:

    -- [ [1,2,3] ,         -l1-    [  1,2,3 ,
    --   [11,12,13,14,15]  -l2-       11,12,13,14,15
    -- ]                           ]
    

    The "rows" are the consecutive values of l in ls = [xs,ys], and the elements in each row are the consecutive values of elements a in each l.

    Nested loops are what list comprehensions essentially are.