例如,可以调用以下函数merge
来合并两个给定的整数列表:
fun
merge
{m,n:nat}
(
xs: list(int, m)
,
ys: list(int, n)
) : list(int, m+n) =
(
case+ xs of
| list_nil() => ys
| list_cons(x, xs2) =>
(
case+ ys of
| list_nil() => xs
| list_cons(y, ys2) =>
if x <= y
then list_cons(x, merge(xs2, ys))
else list_cons(y, merge(xs, ys2))
// end of [if]
)
)
显然,merge
不是尾递归的。如果应用于两个非常长的列表,merge
可能会溢出调用堆栈。有没有办法实现merge
尾递归?
答案 0 :(得分:1)
请注意,stream2list_vt是尾部重复的(并且非常节省内存):
fun
merge
{m,n:nat}
(
xs: list(int, m)
,
ys: list(int, n)
) : List0_vt(int) = stream2list_vt(merge2(xs, ys))
and
merge2
{m,n:nat}
(
xs0: list(int, m)
,
ys0: list(int, n)
) : stream_vt(int) = $ldelay
(
case+ xs0 of
| list_nil() =>
!(streamize_list_elt(ys0))
| list_cons(x0, xs1) =>
(
case+ ys0 of
| list_nil() =>
!(streamize_list_elt(xs0))
| list_cons(y0, ys1) =>
if x0 <= y0
then stream_vt_cons(x0, merge2(xs1, ys0))
else stream_vt_cons(y0, merge2(xs0, ys1))
// end of [if]
)
)
当然,有一种更有效的方法来实现merge
尾递归,而不是上面给出的方法。但是,这个使用线性流的示例显示了一种简单而系统的方式来逐尾递归地构建列表。