您遇到问题是因为if 表达式的then 分支试图做一些没有意义的事情:
x = []
虽然您可以使用 refs 实现可变性,但您不能将值重新分配给标准 ML 中已绑定的标识符,但在这种情况下不需要它们。
在您的情况下,所需函数在概念上的作用是查看列表的第一个元素,通过将其与 k 进行比较来决定是否将其保留在最终结果中,然后对列表的其余部分进行递归:
fun greaterT ([], k) = []
| greaterT (a :: rest, k) =
if a <= k then
a :: greaterT (rest, k)
else
greaterT (rest, k)
不过,上面不是一个好的解决方案,因为第一个递归调用不在尾部位置,所以编译器无法优化生成的代码(原因我在这里不讨论;有很多questions about tail-call optimizations on StackOverflow)。
因此,更好的版本会使用一个额外的参数,它会在其中累积满足<= 谓词的元素。
fun greaterTailRec ([], k, result) = List.rev result
| greaterTailRec (a :: rest, k) =
if a <= k then
greaterTailRec (rest, k, result)
else
greaterTailRec (rest, k, a :: result)
fun greaterT (list, k) = greaterTailRec (list, k, [])
我们可以更进一步,将greaterTailRec 泛化,将具体情况(在这种特殊情况下是比较调用<=)替换为对将列表元素作为参数的函数的更一般调用,并返回bool。因此,我们将得到一个普遍有用的函数,称为filter:
fun filter predicate list =
let
fun recur ([], result) = List.rev result
| recur (a :: rest, result) =
if predicate a then
recur (rest, a :: result)
else
recur (rest, result)
in
recur (list, [])
end
fun greaterT (list, k) =
filter (fn a => a >= k) list
filter helper function 已经定义在List structure 上,所以你的初始函数可以更简洁地表示为:
fun greaterT (list, k) =
List.filter (fn a => a >= k) list