标准ML和函数

时间:2015-10-20 21:59:04

标签: function types sml ml

我遇到一个问题,我被要求提供一个函数,该函数对给定变量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的冲突。

1 个答案:

答案 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 5sum [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