Haskell - 将两个列表一起编织成n个大小的块?

时间:2017-12-19 00:03:09

标签: haskell

我正在练习一些Haskell试卷问题,并且遇到了以下问题

定义一个带有int和的Haskell函数weaveHunks 两个列表,并在给定大小的帅哥中将它们编织在一起。 请务必声明其类型签名。

示例:

weaveHunks 3“abcdefghijklmno”“ABCDEFGHIJKLMNO”

=> “abcABCdefDEFghiGHIjklJKLmnoMNO”

我在Stack Overflow上找到了以下内容,它只是将两个列表编织在一起,但仅限于1个块

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

我在调整这个块以获取大小的问题时遇到了问题,我对Haskell很新,但这是我到目前为止所拥有的

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)

我在最后一行收到错误

  

(无法匹配类型a' with [a]')

(drop n xs)不是列表吗?

2 个答案:

答案 0 :(得分:2)

你非常接近!

通过使用:运算符来预设帅哥,您表示take n xs是结果列表的一个元素,take n ys是下一个元素,依此类推。但实际上在这两种情况下,它都是多个元素。这是[a]实际应该只是a

解决方案是使用++运算符,它预先设置整个列表而不只是单个元素。

这是我写的完整解决方案:

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]

答案 1 :(得分:1)

正如@leftaroundabout所说,由于您的附加列表类型为[a],因此您需要使用++而不是:。考虑到这一点,您的代码将如下所示:

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

如果您有兴趣,还可以使用库函数来完成此任务:

import Data.List.Split

weaveHunks :: Int -> [a] -> [a] -> [a]
weaveHunks n xs ys = concat $ zipWith (++) (chunksOf n xs) (chunksOf n ys)

注意: chunksOf来自Data.List.Split,它将列表拆分为长度为n的子列表,因此此函数的类型为{{1} }。 zipWith根据条件压缩两个列表,在本例中为连接Int -> [a] -> [[a]]concat++列表转换为[[a]]