此代码不接受;
> fun fact 0.0 = 1.0
Error-Real constants not allowed in patterns
> | fact n = n*fact(n-1);
Static Errors
为什么这是?
real
不是等效类型。SML对生成可证明的正确代码的溢价。比较两个实数的平等数字通常不是一个坏主意,因为可能是x = y
数学上的情况,但是由于圆形错误,在运行时x != y
。这是在数值算法的幼稚实现中臭名昭著的错误来源。由于经常是一个坏主意,因此SML只是禁止它。因此,由于不可能将平等的输入与模式1.0
进行比较,因此允许它作为模式是没有意义的。
在相对较少的情况下,您真正想比较两个真实的平等,您可以使用x <= y andalso x => y
。或者(如@AndReasRossberg指出的那样),可以使用标准库函数Real.==
,该功能与Real.==(x,y)
一样使用。最后一个看起来有些奇怪,因此您可以将其声明为Infix操作员:
val == = Real.==
infix 4 ==
,不幸的是,x == y
这些都不能变成模式,尽管它们确实可以写入:
fun fact x = if x == 0.0 then 1.0 else x * fact(x-1.0)
可以按预期的方式工作。另一方面,正如@simonshine指出的那样,如果将其馈送到 n.0
的表单中的任何输入中, n
是int是一个int(即使这仅是由于圆形 - 关闭错误)。这正是SML创造者试图预防的问题。定义fact
取得并返回INT是更有意义的:
fun fact x = if x = 0 then 1 else x * fact(x-1)
(如果您真的想要浮点阶乘,请阅读伽马功能)。
这个最后一个定义可以轻松地转换为您似乎正在尝试的模式匹配形式。