我正在练习一些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)
不是列表吗?
答案 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]]
。