2013-01-13 58 views
2

我对SML非常陌生,我正在尝试清单练习。目标是总结列表的前几个数字并创建一个新列表。例如,输入列表[1, 4, 6, 9]将返回[1, 5, 11, 20]SML清单汇总

这是我迄今为止的解决方案,但我认为问题在于我如何定义函数。

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))); 

回答

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有趣的名字 - 它的关键字。

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是 需要能够定义递归函数(不是很大的惊喜)。实际上,关键字fun 是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)