我对SML很新,我正在尝试列表练习。目标是总结列表的先前数字并创建新列表。例如,输入列表[1, 4, 6, 9]
将返回[1, 5, 11, 20]
。
到目前为止,这是我的解决方案,但我认为问题在于我如何定义函数。
fun rec sum:int list -> int list =
if tl(list) = nil then
hd(list)
else
hd :: sum((hd(tail) + hd(tl(list)))::tl(tl(list)));
答案 0 :(得分:3)
除了你使用rec作为函数名之外,你还有一些小问题需要处理。
您所做的显式类型注释被视为函数结果的注释。 因此,根据你所写的内容,它应该返回一个函数,而不是预期的函数 名单。从以下示例中可以清楚地看到:
- fun rec_ sum : int list -> int list = raise Domain;
val rec_ = fn : 'a -> int list -> int list
当你不对它进行任何检查时,你应该小心使用头部和尾部功能 列表中的元素数量。这可以通过长度函数或(甚至 通过匹配元素数量的模式,更容易,通常更好。
您的代码包含sum作为函数调用,tail作为变量。变量尾巴从来没有 已定义,并使用sum作为函数调用,让我相信你实际上正在使用rec 作为关键字,但不知道它意味着什么。
使用val关键字定义函数时使用关键字rec。在这种情况下,rec是 需要能够定义递归函数(不是一个大惊喜)。实际上,关键词很有趣 是val rec的语法糖(衍生形式)。
以下3个是如何制作的例子:
第一个是简单直接的解决方案。
fun sumList1 (x::y::xs) = x :: sumList1 (x+y::xs)
| sumList1 xs = xs
第二个例子,使用一个辅助函数,带有一个附加参数(一个累加器)。列表以相反的顺序构造,以避免使用慢速追加(@)运算符。因此我们在返回之前反转列表:
fun sumList2 xs =
let
fun sumList' [] acc = rev acc
| sumList' [x] acc = rev (x::acc)
| sumList' (x :: y :: xs) acc = sumList' (y+x :: xs) (x :: acc)
in
sumList' xs []
end
最后一个示例显示了如果使用标准列表函数,它可以变得多么简单。这里使用左侧折叠来遍历所有元素。再次注意,列表以相反的顺序构造,因此它作为最后一步反转:
fun sumList3 [] = []
| sumList3 (x::xs) = rev (foldl (fn (a, b) => hd b + a :: b) [x] xs)
答案 1 :(得分:2)
试试这个 -
fun recList ([], index, sum) = []
| recList (li, index, sum) =
if index=0 then
hd li :: recList (tl li, index+1, hd li)
else
sum + hd li :: recList (tl li, index+1, sum + hd li)
fun recSum li = recList (li, 0, 0)
在你的情况下 -
recSum([1,4,6,9]) ;
将给出
val it = [1,5,11,20] : int list
也不要将rec
用作有趣的名称-it关键字。