Ocaml 在这种情况下,为什么编译器不再抱怨“type unit”?
如果我做了Ocaml 在这种情况下,为什么编译器不再抱怨“type unit”?,ocaml,Ocaml,如果我做了让f1 x=x;x+1,编译器将抱怨:警告10:此表达式应具有类型单位。 如果我做了让f2 f=f();5,编译器将给出valf2:(单位->a)->int= 问题 类型系统推断f是一个以单元为参数并返回'a的函数。但是如果它返回'a,为什么编译器不给出警告10 若编译器并没有给出警告10,这意味着它认为f()返回单元,不是吗?那么为什么它会给出'a作为返回类型呢 若编译器并没有给出警告10,这意味着它认为f()返回单位,不是吗 显然,如果编译器给出f2类型(unit->'a)->in
让f1 x=x;x+1
,编译器将抱怨:警告10:此表达式应具有类型单位。
如果我做了让f2 f=f();5
,编译器将给出valf2:(单位->a)->int=
问题
f
是一个以单元
为参数并返回'a
的函数。但是如果它返回'a
,为什么编译器不给出警告10
警告10
,这意味着它认为f()
返回单元,不是吗?那么为什么它会给出'a
作为返回类型呢
f2
类型(unit->'a)->int
,这意味着它认为f
返回'a
你在编译器的位置上会做什么
- 您是否警告说,
可能会应用于某些返回非单位结果的函数,尽管它可能永远不会实际应用于这些函数f2
- 您是否会给
类型f2
,并降低它的有用性,强制它仅用于返回(unit->unit)->int
的函数()
- 您是否会发明一个复杂的延迟警告系统,其中
的类型为f2
,但如果它应用于不返回(unit->'a)->int
的函数,则会在编译时产生额外的警告?您是否会使该系统跨模块工作(功能的延迟警告必须是模块签名的一部分)()
警告只是有用的提示,而不是保证。当有疑问时,不发出警告是通常的解决方案(几乎所有编译器都采用这种解决方案,而不仅仅是OCaml编译器)。让我补充一下Pascal的答案 试一试
f1'
和f2'
不会给您任何警告,但f1'
和f2'
会给您警告
为什么只针对f1''
和f2''
?因为OCaml类型检查器肯定知道e1中e1的类型;e2
不是单元
(它们是列表
)
对于f1'
和f2'
,e1
的类型是类型变量'a
。根据f1'
和f2'
的使用方式,它们可能被实例化为unit
,因此它们有可能被“正确”使用。考虑到这种可能性,编译器不会警告他们
我个人更喜欢在e1中强制使用e1的类型;e2
beunit
。但是OCaml在这里更轻松。我认为这是编译器遗留的行为。使用-strict sequence
修复它:
$ ocaml
# let f2 f = f(); 5;;
val f2 : (unit -> 'a) -> int = <fun>
如果编译器给f2类型(unit->'a)->int,这意味着它认为f2返回'a
为什么f2
肯定被认为是返回int
,不是吗?@JacksonTale那是个打字错误,我的意思是“…那f
返回'a
”啊,好的,那可以explain@JacksonTale是的,'a
可以实例化为任何类型,包括单元
,否则将无法应用标识(类型为'a->'a
到()
。但这非常有用(因此可能):让id x=x在id()中@PascalCuoq啊,好吧,我认为单元类型是特殊的,是对'a
类型的补充
$ ocaml
# let f2 f = f(); 5;;
val f2 : (unit -> 'a) -> int = <fun>
$ ocaml -strict-sequence
# let f2 f = f(); 5;;
val f2 : (unit -> unit) -> int = <fun>
true: strict_sequence