您的代码存在多个问题。
从这一行开始
| fibl n = fibl [n]
您正在匹配前两行中的整数列表。因此,您的函数必须将这样的列表作为输入。然而,在上面的行中,您正在获取这个整数列表n 并递归地调用您的函数,并将n 打包在另一个列表fibl [n] 中。
但请注意,此匹配在修复后会产生无限循环!
另一个问题是你的最后一个匹配是多余的,因为上面的匹配会捕获所有输入,导致你的最后一个匹配更新。
你在上一场比赛中也有一些错误。请注意,您的函数将其结果作为单例列表返回。在您的函数f 中,您尝试添加fibl 函数的结果(即一个int 列表),这是可能的。
在这里,您要么必须从列表中“拉出”数字,要么做一些完全不同的事情。
由于您尝试生成斐波那契数列,我建议您做一些完全不同的事情,因为您当前的方法只生成一个包含两个斐波那契数列的列表。
我建议您从一个幼稚的解决方案开始;具有将生成第 n 个斐波那契数的函数,然后通过反复应用此函数生成列表。
一些例子
根据要求,这里有一些示例说明如何天真地做到这一点。
首先我们定义一个函数来生成第 n 个斐波那契数。
fun fib 0 = 0
| fib 1 = 1
| fib n = fib (n-1) + fib (n-2)
然后可以通过数字列表轻松映射此函数,生成这些特定斐波那契数字的列表
- val fibLst = map fib [0,1,2,3,4,5,6,7,8];
val fibLst = [0,1,1,2,3,5,8,13,21] : int list
但是我们也可以创建一个函数,它会生成一个列表 0...n,然后将 fib 函数应用于该列表。
fun genFib n = List.tabulate (n, fib);
或者没有 List.tabulate 函数
fun genFib1 n =
let
fun loop 0 acc = fib 0 :: acc
| loop m acc = loop (m-1) (fib m :: acc)
in
loop (n-1) []
end
显然 fib 函数可以实现得更好,我们的列表生成函数可以利用下一个斐波那契数的创建方式。您会注意到,下面的函数在生成包含前 40 个斐波那契数的列表时要快得多。
fun genFib2 n =
let
fun loop 0 _ _ acc = rev acc
| loop m f_1 f_2 acc = loop (m-1) f_2 (f_1 + f_2) (f_2 :: acc)
in
loop (n-1) 0 1 [0]
end
上面有一些关于 SML 中整数大小的问题(您可以生成第 44 个斐波那契数,但不能生成第 45 个)。所以我们可以扩展fib函数以使用任意精度整数IntInf,结合上面的想法
fun fibInf n : IntInf.int =
let
fun loop 0 f_1 _ = f_1
| loop m f_1 f_2 = loop (m-1) f_2 (f_1 + f_2)
in
loop n 0 1
end
现在它既“快速”又可以生成前 100 个或更多斐波那契数
fun genFibInf n = List.tabulate (n, fibInf);
- genFibInf 1000;
val it = [0,1,1,2,3,5,8,13,21,34,55,89,...] : IntInf.int list
- List.nth(it, 700);
val it =
8747081495575284620397841301757132734236724096769738107423043259252750#
: IntInf.int