我实现了以下求和函数:
fun cumsum_reverse (xs: int list) =
if null xs then [0]
else
let val tl_cumsum = cumsum_reverse (tl xs)
in
hd xs + hd tl_cumsum :: tl_cumsum
end
fun reverse (first: int list, second: int list) =
if null first
then
second
else
reverse (tl first, hd first :: second)
fun cumsum (xs: int list) =
tl(reverse(cumsum_reverse(reverse(xs, [])), []))
测试用例:
val test = cumsum[1,4,20] = [1,5,25]
有什么方法只能使用一个功能来实现吗?
答案 0 :(得分:2)
我将根据通用scanl
函数对此进行定义。它类似于foldl
,但会产生一个中间结果列表。它的工作原理与累积总和非常相似,但是使用了+
运算符和参数化的默认元素。它在标准库中不可用,但也可能已经存在。
fun scanl _ _ [] = []
| scanl f y0 (x::xs) =
let val y1 = f (x, y0)
in y1 :: scanl f y1 xs
end
然后:
val cumsum = scanl op+ 0
有什么方法只能使用一个功能来实现吗?
这取决于您所说的“仅一个功能”。
只有一个功能吗? cumsum
仅将一个列表作为输入,并且您需要一个额外的参数来跟踪累积的总和。由于累加结果的函数不能直接为cumsum
,因此需要两个函数。那么,您的意思是“ cumsum
之外的一个命名函数”吗?然后scanl
或matt的内部帮助函数将解决此问题。
如果您只能使用标准库函数定义cumsum
:
val cumsum = tl o rev o foldl (fn (x, y::ys) => x + y :: y :: ys) [0]
然后cumsum
成为您声明的唯一函数。
如果您只能使用单个标准库函数定义cumsum
,那么我会使用foldl
:
val cumsum = (fn (_::xs) => xs) (* tl *)
o foldl op:: [] (* rev *)
o foldl (fn (x, y::ys) => x + y :: y :: ys) [0]
然后cumsum
成为您声明的唯一函数,并且只使用了一个名为standard-library的函数即可。 (如果它不是标准库函数,则必须先声明它,然后再声明两个函数。)
但这变得有点傻了。 :-)
答案 1 :(得分:1)
当然,这是我仍然使用多种功能的一种方法, 但是它只是保持累加和并从0开始递归的助手。
但是,递归循环完全发生在helper函数中,该函数的名称相同,目的是故意遮盖第一个。
fun cumsum (xs : int list) =
let fun cumsum (x::xs, sum) = let val foo = x + sum in foo::cumsum(xs, foo) end
| cumsum ([], _) = []
in cumsum (xs, 0) end