不接受此代码;
> fun fact 0.0 = 1.0
Error-Real constants not allowed in patterns
> | fact n = n*fact(n-1);
Static Errors
为什么会这样?
答案 0 :(得分: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所指出的那样,如果你输入不是的n.0
形式的n
,那么这将会崩溃。如果这只是由于四舍五入的错误)。这正是SML的创建者试图阻止的那种问题。定义fact
以获取和返回整数更有意义:
fun fact x = if x = 0 then 1 else x * fact(x-1)
(或 - 如果你真的想要一个浮点因子,请阅读伽玛函数。)
最后一个定义可以很容易地转换为您似乎正在尝试的模式匹配形式。