如何在sml中重复地递归调用另一个函数?

时间:2017-03-20 19:53:49

标签: recursion sml smlnj

  

我有一个名为mergeP的函数:

fun mergeP(nil) = nil
| mergeP(x::[]) = x::[]
| mergeP(x::y::zs) = (x @ y)::mergeP(zs);
  

如果调用mergeP,则会:mergeP([[1],[2],[3],[4]])   返回[[1,2],[3,4]]。我想创建一个名为mergeS的函数   这是递归的,反复调用mergeP直到子列表   等于一个列表。因此,如果调用mergeS,则:   mergeS([[1],[2],[3],[4]])它会反复拨打mergeP直到它   等于:[1,2,3,4]。这是我的尝试:

- fun mergeS(nil) = nil
= |mergeS(xs) = mergeS(mergeP(xs));
  

但这给了我错误:

stdIn:6.1-6.26 Warning: type vars not generalized because of
   value restriction are instantiated to dummy types (X1,X2,...)
val it = [] : ?.X1 list

2 个答案:

答案 0 :(得分:2)

  

我相信我得到了它的工作:

fun mergeS(nil) = nil
| mergeS([xs]) = xs
| mergeS(xs) = mergeS(mergeP(xs));

答案 1 :(得分:0)

您的解决方案效果很好,但可以跳过mergeP并直接定义mergeS

fun mergeS [] = []
|   mergeS ([]::xss) = mergeS xss
|   mergeS ((x::xs)::xss) = x :: mergeS (xs::xss);

在第三行中,函数递归地拉出第一个内部列表中的元素,并将它们添加到最终结果中。当第一个列表中没有更多内容可以完成时,您已完成它,第二行将其抛弃并继续处理剩余的内部列表。当没有更多内部列表要处理时,您将在第1行中找到基础案例并完成。

您正在调用mergeS的此功能将更加惯用地称为flatten,因为它会使#34;变平。列表列表到单个列表中。这会使单个级别变平。您还可以编写一个展平的函数,例如两个级别(单个列表的列表列表),但是,正如@molbdnilo在注释中指出的那样,在SML中不可能编写一个可以将嵌套列表展平为任意嵌套级别的函数。你不能写一个例如将与[[[1,2]],[[3],[4]]]以及[[1],[2],[3],[4]]一起使用,因为SML的类型系统没有对应于任意嵌套列表的类型构造函数。