Warning: file_get_contents(/data/phpspider/zhask/data//catemap/6/haskell/10.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Haskell 如何从两个列表中创建一个列表以及从这些列表中创建元素_Haskell_Recursion - Fatal编程技术网

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 : ...