应对任意深度嵌套列表

时间:2014-02-25 18:35:10

标签: list haskell recursion

我正在编写一段代码,通过吃掉包含输入元素的列表来产生大量结果。说[i1,i2,i3,i4]

产生结果的函数将以所有可能的方式组合前两个:o1,o2和o3,并用计算结果替换输入:

[[o1,i3,i4],[o2,i3,i4],[o3,i3,i4]]

从现在开始,我希望依靠递归来生成单个列表的列表,这些列表是组合输入的结果,但是我仍然在应对任意嵌套列表时遇到问题,很可能因为我是希望将输出映射回这种(某种)功能:

tides :: [a] -> [a]
tides (i1:i2:is) =  map tides ((makeResult i1 i2):is) 
tides [] = []

- makeResult生成所述输出的位置

这不起作用,我相信我不会发现这样的工作功能。描述这种递归的正确方法是什么?

1 个答案:

答案 0 :(得分:12)

列表类型([])不执行任意嵌套,它在其他类型的顶部引入了一个级别的“列表”。

[1,2,3]            :: [Int]
[(), (), ()]       :: [()]
[[1,2,3], [4,5,6]] :: [[Int]]

这意味着您的嵌套列表集中的每个子树必须具有相同的深度。此外,这个确切的深度必须以类型(静态!)表示,因此您必须在编译时知道它。

如果你习惯了更多动态列表,那么这听起来很荒谬。然而,真正发生的事情是,Haskell列表只是比其他地方使用的列表更具限制性的类型 - 这些列表实际上是玫瑰树:

data Rose a = Rose [Rose a] | Leaf a

Rose a类型的值是单身(包含在Leaf中)或Rose a列表中的每一个,每个 单身或另一层列表,区别仅在运行时可用。

(((1 (2 3)) 
  (4 5) 6) 
 (1 2))

Rose [ Rose [Leaf 1, Rose [Leaf 2, Leaf 3]]
     , Rose [Rose [Leaf 4, Leaf 5], Leaf 6]
     , Rose [Leaf 1, Leaf 2]]