0

给定一个数字列表,我想创建一个新列表,其中索引i 处的元素是之前所有元素的总和i-1

例如 :

[1,4,6,9] ->  [1,5,11,20]

我写了以下代码:

fun sum nil = 0 
| sum [x]=x 
| sum(x::rest)=(x+hd(rest))::sum(rest);

但我得到了这个:

- fun sum nil = 0
= | sum [x]=x
= | sum(x::rest)=(x+hd(rest))::sum(rest);
stdIn:306.16-306.39 Error: operator and operand don't agree [literal]
  operator domain: int * int list
  operand:         int * int
  in expression:
    x + hd rest :: sum rest

我可以看到递归规则(x+hd(rest))::sum(rest);是问题的原因,但我该如何解决呢?

问候

4

1 回答 1

5

看看你的基本情况。您希望函数返回一个列表,因此基本案例应该返回列表。

fun sum []      = []
  | sum [x]     = [x]
  | sum (x::xs) = ...

我替换nil[]因为我更喜欢它 - 这并不重要。

另一件事 - 永远不要使用hdandtl运算符(有例外,但现在,不要使用)。当然,在你的函数中,它不会成为问题,因为你处理了它会出现的情况,但还有另一个原因。如果你这样做:

fun foo [] = ...
  | foo (x::y::xs) = ...

SML 会告诉您模式匹配并不详尽,也就是说,您错过了一些模式,这意味着您在编译时而不是在运行时捕获错误。

这是您的功能的一个有效版本。

fun sum [] = []
  | sum [x] = [x]
  | sum (x::y::xs) = x::sum (x+y::xs)

我将添加移到递归调用中,因为如果您作为第一件事添加,那么结果的第一个元素将是原始列表的前两个元素加在一起。

于 2013-02-17T17:30:17.907 回答