我故意将 x 添加到这个函数的末尾
let myMax x y =
if x > y then x else y
x
我原以为 x 和 y 参数仍然是“a 类型”,但我得到了这个签名:
myMax : x:unit -> y:unit -> unit
为什么这些参数被推断为具有单位类型?
编辑: 谢谢@gilles 的回答。考虑这两个函数:
let foo x y =
0 // warning
x
val foo : x:'a -> y:'b -> 'a
let foo2 x y =
if x > y then x else y // no warning
x
val foo2 : x:unit -> y:unit -> unit
两个签名有何不同? 似乎在第二个函数中,编译器将比较结果解释为 x 或 y 作为单位
最佳答案
让我们写一个更简单的例子:
> fun x -> x; 0;;
val it : unit -> int = <fun:clo@5>
在复合表达式中,分号/换行符之前的表达式必须具有单位类型。如果您想使用具有“真实”值的表达式(即除单位之外的任何类型),您需要显式忽略它,或将其绑定(bind)到无变量模式。如果表达式的类型不能与unit
统一,编译器会提醒您:
> fun x -> 0; x;;
fun x -> 0; x;;
---------^
stdin(7,10): warning FS0020: This expression should have type 'unit', but has type 'int'.
Use 'ignore' to discard the result of the expression,
or 'let' to bind the result to a name.
val it : x:'a -> 'a = <fun:clo@7-1>
可以有一个类型规则,允许 ;
之前的任何类型 - 毕竟该值会被忽略,因此它的类型并不重要 - 但这很容易导致意外丢弃重要的返回值。因此,如果您想忽略该值,请明确执行:
let myMax x y =
ignore (if x > y then x else y)
x
或
let myMax x y =
let _ = if x > y then x else y
x
关于types - 为什么这些参数被推断为具有单位类型?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37093957/