2

不接受此代码;

> fun fact 0.0 = 1.0
Error-Real constants not allowed in patterns
> | fact n = n*fact(n-1);
Static Errors

为什么是这样?

4

1 回答 1

5

real不是相等类型。SML 非常重视生成可证明正确的代码。比较两个实数是否相等通常不是一个坏主意,因为在x = y 数学上可能是这种情况,但是由于舍入误差,x != y在运行时。这是数值算法的幼稚实现中臭名昭著的错误来源。由于这通常是一个坏主意,SML 干脆禁止它。由于不可能将输入与模式进行比较1.0,因此将其作为模式是没有意义的。

在您确实想比较两个实数是否相等的相对少数情况下,您可以使用x <= y andalso x => y. 或者(正如@AndreasRossberg 指出的那样),可以使用Real.==Real.==(x,y). 最后一个看起来有点奇怪,因此您可以将其声明为中缀运算符:

val ==  = Real.==
infix 4 ==

然后x == y很不幸,这些都不能变成模式,尽管它们确实可以编写:

fun fact x = if x == 0.0 then 1.0 else x * fact(x-1.0) 

可以按预期工作。另一方面,正如@SimonShine 指出的那样,如果您向它提供任何不是int形式的n.0输入,这将崩溃n(即使这只是由于舍入错误)。这正是 SML 的创建者试图阻止的问题。fact定义获取和返回整数更有意义:

fun fact x = if x = 0 then 1 else x * fact(x-1)

(或者——如果你真的想要一个浮点阶乘,请阅读 gamma 函数)。

最后一个定义可以很容易地转换为您似乎正在尝试的模式匹配形式。

于 2016-12-08T16:36:28.097 回答