为什么编译器在这种情况下停止抱怨`type unit`?

Jac*_*ale 5 ocaml

如果我这样做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>.

问题

  1. 类型系统推断f是一个unit以参数为参数并返回的函数'a.但如果它返回'a,为什么编译器不给出Warning 10
  2. 如果编译器没有给出Warning 10,则表示它认为f()返回unit,不是吗?那为什么它'a作为返回类型给出?

Pas*_*uoq 6

如果编译器没有给出警告10,则表示它认为f()返回单位,不是吗?

显然,如果编译器给出f2了类型(unit -> 'a) -> int,那意味着它认为f返回'a.

什么将的编译器的地方吗?

  • 您是否会警告f2可能会应用于某些返回非单位结果的函数,尽管它实际上可能永远不会被应用?

  • 你会给出f2类型(unit -> unit) -> int并使其不那么有用,强制它只用于返回的函数()吗?

  • 你会发明一个复杂的推迟警告系统,其中f2有类型,(unit -> 'a) -> int但如果它被应用于一个不返回的函数,它会在编译时产生一个额外的警告()吗?您是否会使这个系统跨模块工作(函数的推迟警告必须是模块签名的一部分)?

警告只是有用的提示,而不是保证.如果有疑问,不发出警告是通常的解决方案(几乎所有编译器都采用这种解决方案,而不仅仅是OCaml编译器).


Tho*_*ard 5

我认为这是编译器的遗留行为.使用-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)