我遇到一个问题,我被要求提供一个函数,该函数对给定变量x
中的所有元素求和。例如,sum([5,5,5])
应该返回15。
当我测试像这样的单个整数的总和时,我的麻烦就起作用了:sum(5)
该功能应该可以在单个数字和数字列表之间返回第四个。我知道要做到这一点,我需要一个有Int of int | Null | ...
我的问题是如何让下面的代码适用于测试用例sum(5)
;
fun sum(x) = if x = nil
then 0
else hd(x) + sum(tl(x))
val result = sum([5,5]);
我想我需要这样的东西:
else if (int? x) then x
else hd(x) + sum(tl(x))
但是当我用我的数据类型执行此操作时,我得到int vs int list的冲突。
答案 0 :(得分:2)
快速回答你的问题:这是不可能的。正如您所说,您需要一种允许您保存单个整数或整数列表的数据类型。您可以引入类似的类型:
datatype my_int = SingleInt of int | ManyInts of int list
fun sum (SingleInt i) = i
| sum (ManyInts is) = foldl op+ 0 is
但这真的很愚蠢,因为如果你考虑一下,类型int list
已经可以包含一个整数或一个整数列表(甚至是零整数,当涉及到总和时,明确的意义)。因此,将函数扩展到处理列表之外是没有意义的。
无论您是否使用自定义类型,您都无法访问重载,因此无法在标准ML中编写sum 5
或sum [5,5,5]
。在其他函数语言中,如Haskell,您可以使用类型类实现这种重载。
作为旁注,尝试使用模式匹配而不是if-then-else。你的求和函数是:
fun sum [] = 0
| sum (x::xs) = x + sum xs
或制作尾递归版本:
fun sum xs =
let fun helper [] result = result
| helper (x::xs) result = helper xs (x+result)
in helper xs 0 end
或者只是简单地使用折叠:
val sum = foldl op+ 0