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?
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]