haskell

Haskell - Weave two lists together in chunks of n size?


I am practicing some Haskell exam paper questions, and have come across the following

Define a Haskell function weaveHunks which takes an int and two lists and weaves them together in hunks of the given size. Be sure to declare its type signature.

Example:

weaveHunks 3 "abcdefghijklmno" "ABCDEFGHIJKLMNO"

=> "abcABCdefDEFghiGHIjklJKLmnoMNO"

I have found the following on Stack Overflow, which is just too weave two lists together but only in chunks of 1

weaveHunks :: [a] -> [a] -> [a]
weaveHunks xs [] = xs
weaveHunks [] ys = ys
weaveHunks (x:xs) (y:ys) = x : y : weaveHunks xs ys

I am having problems adjusting this to take chunks fo n size, I am very new to Haskell but this is what I have so far

weaveHunks :: Int -> [a] -> [a] -> [a]
weaveHunks n xs [] = xs
weaveHunks n [] ys = ys
weaveHunks n xs ys = (take n xs) : (take n ys) : weaveHunks n (drop n xs) (drop n ys)

I am getting an error on the last line

(Couldn't match type a' with[a]')

Is (drop n xs) not a list?


Solution

  • You're very close!

    By using the : operator to prepend the hunks, you're expressing that take n xs is one element of the result list, take n ys the next, and so on. But actually in both cases it's multiple elements you're prepending. That's the [a] that should actually be just a.

    The solution is to use the ++ operator instead, which prepends an entire list rather than just a single element.

    This is the full solution as I'd write it:

    weaveHunks :: Int -> [a] -> [a] -> [a]
    weaveHunks _ xs [] = xs
    weaveHunks _ [] ys = ys
    weaveHunks n xs ys = xHunk ++ yHunk ++ weaveHunks n xRemain yRemain
     where [(xHunk, xRemain), (yHunk, yRemain)] = splitAt n <$> [xs,ys]