我在学习SML方面取得了一些进展,试图巩固我对一些最基本概念的理解。以下练习证明仍有许多东西需要学习。
我被要求实现一个名为add的函数,它接收两个数字并返回它们的总和。问题是,add应该接收一个整数和实数的不相交联合,并以下列方式返回一个不相交的联合:如果收到的两个数字都是整数,它应该将整数作为整数返回。否则,如果两个参数中的一个是真实的,则应将该总和作为实数返回。
最合理的解决方案是使用数据类型,但我特别指示不要以任何方式,形状或形式使用它。换句话说,我应该实现某种机制来确定参数的类型,并且如下所示,确定返回类型。
所有的尝试都是徒劳的。 SML推断我的参数是一种特定类型(不是这种情况),或者它要求返回值是某种类型,这是可以理解的但仍然令人沮丧。我不知道如何克服SML的输入限制。如果它有用,我暗示要使用元组。
答案 0 :(得分:4)
我发现这个问题有点奇怪,因为在SML中,短语" disjoint union"通常表示由datatype
声明定义的标记联合。关于使用元组的暗示让我想到了......选项。有一种自然的方式来考虑int
和real
作为int option * real option
的子类型的不相交联合,例如5
对应(SOME 5, NONE)
,5.0
对应(NONE, SOME 5.0)
。我知道在类型级别上没有办法强制执行隐含的限制,即唯一有效的模式涉及一个SOME
和一个NONE
,但您可以定义函数,以便在尝试使用它们时它们会崩溃使用(NONE,NONE)
或(SOME n, SOME r)
模式 - 通过不提供这些模式的定义或显式引发错误。这将阻止您的函数被用于除可以解释为位于联合类型中的值之外的任何其他函数。
使用它,定义函数add
相对容易,例如
add (SOME 1, NONE) (SOME 5, NONE)
评估为(SOME 6, NONE)
。由于这是一项任务,我不想再说什么了。
我并不完全确定这是你的导师所想到的那种,尽管它似乎是一种合理的解释。
答案 1 :(得分:3)
我真的建议您查看John Coleman提交的答案,因为这是最合理的方法。但是,我的导师有一些不同的想法。因此,为了后代,这是我原始的,完全不切实际的实现,这是预期的:
fun add (a, b, _, _, 0) = (a+b, 0.0)
| add (_, b, x, _, 1) = (0, real(b) + x)
| add (_, _, x, y, _) = (0, x + y);
与C union数据类型非常相似。一个由5个元素组成的元组用于向函数发送参数:2个整数条目,2个实际条目和一个标记,用于区分添加它们的3种可能方式(int / int,int / real,real / real)。同样,这只是出于教育目的而编写,因此对于此功能的任何实际使用,请参阅John Coleman的回答。