如果我这样做let f1 x = x; x+1,编译器会抱怨:Warning 10: this expression should have type unit.
如果我这样做let f2 f = f(); 5,编译器会给出val f2 : (unit -> 'a) -> int = <fun>.
问题
f是一个unit以参数为参数并返回的函数'a.但如果它返回'a,为什么编译器不给出Warning 10?Warning 10,则表示它认为f()返回unit,不是吗?那为什么它'a作为返回类型给出?如果编译器没有给出警告10,则表示它认为f()返回单位,不是吗?
显然,如果编译器给出f2了类型(unit -> 'a) -> int,那意味着它认为f返回'a.
什么将你的编译器的地方吗?
您是否会警告f2可能会应用于某些返回非单位结果的函数,尽管它实际上可能永远不会被应用?
你会给出f2类型(unit -> unit) -> int并使其不那么有用,强制它只用于返回的函数()吗?
你会发明一个复杂的推迟警告系统,其中f2有类型,(unit -> 'a) -> int但如果它被应用于一个不返回的函数,它会在编译时产生一个额外的警告()吗?您是否会使这个系统跨模块工作(函数的推迟警告必须是模块签名的一部分)?
警告只是有用的提示,而不是保证.如果有疑问,不发出警告是通常的解决方案(几乎所有编译器都采用这种解决方案,而不仅仅是OCaml编译器).
我认为这是编译器的遗留行为.使用-strict-sequence来解决它:
$ ocaml
# let f2 f = f(); 5;;
val f2 : (unit -> 'a) -> int = <fun>
Run Code Online (Sandbox Code Playgroud)
但:
$ ocaml -strict-sequence
# let f2 f = f(); 5;;
val f2 : (unit -> unit) -> int = <fun>
Run Code Online (Sandbox Code Playgroud)
如果你使用ocamlbuild,你应该把它放在你的_tags文件中:
true: strict_sequence
Run Code Online (Sandbox Code Playgroud)