1

i've tried to create a Haskell function that is merging 2 lists into a single list, where even indices in the new list are from list 1 and the odd are from list 2. Fill with 0's if not the same size.

For example:

[1] [10,15,20] => [1,10,0,15,0,20] 
[2,3] [4,5] => [2,4,3,5]

I've tried to create a couple of versions but with no luck.

How can I create such a thing?

Will Ness
  • 70,110
  • 9
  • 98
  • 181
user6351755
  • 21
  • 1
  • 6
  • 1
    Look at the implementation of `zip` at https://hackage.haskell.org/package/base-4.12.0.0/docs/Prelude.html#v:zip – mschmidt Nov 25 '19 at 10:42

2 Answers2

2

There is a interleave function, that does something similar, however, not exactly that. It 'merges' lists until one of them ends.

So you can write that function by yourself:

merge :: [Int] -> [Int] -> [Int]
merge (x:xs) (y:ys) = x : y : merge xs ys
merge (x:xs) [] = x : 0 : merge xs []
merge [] (y:ys) = 0 : y : merge [] ys
merge _ _ = []

When we have some elements on both sides, we take both of them. When one of elements is absent, we take 0 instead of it. In all other cases (it is the merge [] [] case) we end up with our recursion and return an empty list.

We can also slightly generalize our function to support any number-like type:

merge :: Num a => [a] -> [a] -> [a]
merge (x:xs) (y:ys) = x : y : merge xs ys
merge (x:xs) [] = x : 0 : merge xs []
merge [] (y:ys) = 0 : y : merge [] ys
merge _ _ = []

Also, we can go further and use def from Data.Default package to get the default value for our type, so we can use this function with not only lists of numbers:

import Data.Default

merge :: Default a => [a] -> [a] -> [a]
merge (x:xs) (y:ys) = x : y : merge xs ys
merge (x:xs) [] = x : def : merge xs []
merge [] (y:ys) = def : y : merge [] ys
merge _ _ = []
Yuri Kovalenko
  • 1,325
  • 9
  • 19
0

Using the idea from this answer of mine, using the transpose :: [[a]] -> [[a]] function,

interweaveWith :: a -> [a] -> [a] -> [a]
interweaveWith def xs ys =
   -- 0 [1] [10,15,20] => [1,10,0,15,0,20] 
   concat $
      zipWith const
         (transpose [ xs ++ repeat def,      -- no limit, padded with def
                      ys ++ repeat def ])
         (transpose [xs, ys])                -- as long as the longest
Will Ness
  • 70,110
  • 9
  • 98
  • 181