此函数采用两个整数并返回[a,b]
范围内所有整数的列表这是我写的解决方案。
let rec range_rec l a b =
if (a=b) then l@[b]
else range_rec (l@[a], a+1, b);;
let range a b = range_rec [] a b;;
我遇到错误“错误:此表达式的类型为int list * int * int,但表达式的类型为int”。有人可以说明为什么我会收到这个错误吗?
感谢。
答案 0 :(得分:7)
它应该是这样的:
let rec range_rec l a b =
if a = b then l @ [b]
else range_rec (l @ [a]) (a + 1) b;;
let range a b = range_rec [] a b;;
我做了什么:
loop
更改为range_rec
(l@[a], a+1, b)
更改为(l @ [a]) (a + 1) b
。第一个是三元组,第二个是curried函数的3个参数。if (a = b) then
可以写为if a = b then
。最后,通过循环“向后”,使用::
代替@
可以提高功能效率。例如,像gasche所示。
答案 1 :(得分:6)
从性能角度来看,l @ [elem]
操作非常糟糕:由于a @ b
在a
的长度上是线性的,因此在列表末尾添加元素的长度是线性的。列表,使您的整个range_rec
定义在|b-a|
中呈二次方式。要做的就是更改代码,以便您可以使用常量elem::l
操作。
let rec range a b =
if a > b then []
else a :: range (a + 1) b
您可以进行其他优化,例如使其尾递归,但至少此解决方案的复杂性是正确的。
答案 2 :(得分:1)
为了改进gasche已经提出的解决方案,可以将其设置为尾递归。
let int_range a b =
let rec int_range_rec l a b =
if a > b then l
else int_range_rec (b :: l) a (b - 1)
in (int_range_rec [] a b);;