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
    作为返回类型呢
  • 若编译器并没有给出警告10,这意味着它认为f()返回单位,不是吗

    显然,如果编译器给出
    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
    be
    unit
    。但是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