Haskell 如何从两个列表中创建一个列表以及从这些列表中创建元素
我是哈斯克尔的新手。我试图使用递归来编写一个函数,给定两个列表(它们必须是同一类型),交错它们的元素(在第一个和第二个列表之间交替使用元素)。当其中一个列表中没有更多的元素时,它会停止,结果是列表达到了这个程度Haskell 如何从两个列表中创建一个列表以及从这些列表中创建元素,haskell,recursion,Haskell,Recursion,我是哈斯克尔的新手。我试图使用递归来编写一个函数,给定两个列表(它们必须是同一类型),交错它们的元素(在第一个和第二个列表之间交替使用元素)。当其中一个列表中没有更多的元素时,它会停止,结果是列表达到了这个程度 interChange :: [a] -> [b] ->[(a,b)] interChange _ [] = [] interChange [] _ = [] interChange (x:xs) (y:ys) = (x,y) : interChange xs ys 我的
interChange :: [a] -> [b] ->[(a,b)]
interChange _ [] = []
interChange [] _ = []
interChange (x:xs) (y:ys) = (x,y) : interChange xs ys
我的输出示例:
interChange [1,2,3] [4,5,6]
[(1,4),(2,5),(3,6)]
所需输出的示例如下:
interChange [1,2,3] [4,5,6]
[1,4,2,5,3,6]
感谢您的帮助您的
交换
与前奏相同
要编写指定的函数,实际上需要一对相同类型的列表。我们正在输出一个特定类型的列表,因此进入该列表的所有元素也必须具有该类型
interleave :: [a] -> [a] -> [a]
您可以通过传递一个Bool
来以递归方式实现这一点,该Bool指示您应从哪个列表中获取下一个元素:
interleave = go True
where go _ [] ys = ys
go _ xs [] = xs
go True (x:xs) ys = x : go False xs ys
go False xs (y:ys) = y : go True xs ys
在go
的最后两个子句之间进行求值乒乓,直到其中一个输入列表为空,然后我们只返回另一个列表的其余部分。(如果您希望它的行为更像zip
,您可以让它通过返回[]
而不是在这些情况下返回xs
或ys
来截断输出。)
但我总是建议尽可能避免在更高级别上进行递归编程。我们可以将此函数编写为管道:
zip
map(\(x,y)->[x,y])
concat
interleave xs ys = concat $ map (\(x, y) -> [x, y]) $ zip xs ys
我发现这段代码比递归代码更容易理解,递归代码要求您对控制流进行推理——它只是一系列高级指令
顺便说一句,您可以通过将中间映射
拖到concat
或zip
中来省略它:
interleave xs ys = concatMap (\(x, y) -> [x, y]) $ zip xs ys
interleave xs ys = concat $ zipWith (\(x, y) -> [x, y]) xs ys
当使用两个非空列表
(x:xs)
和(y:ys)
调用interChange
时,输出应该是一个列表,从x
开始,然后是y
,然后是更多内容。所以你应该写一些
interChange (x:xs) (y:ys) = x : y : ...
非常感谢您的重播,您的代码非常好。但是,它不满足最后一个条件。当其中一个列表中没有更多的元素时,它将停止。您的代码给出如下输出:[1,2,3,4][6,7,8]=[1,6,2,7,3,8,4],但它应该是[1,6,2,7,3,8],我相信您可以找到如何修改代码以适应此练习。
interChange (x:xs) (y:ys) = x : y : ...