【问题标题】:OCaml - confusion from type alias (warning 40)OCaml - 来自类型别名的混淆(警告 40)
【发布时间】:2018-04-13 14:24:16
【问题描述】:

我不明白为什么 OCaml 无法弄清楚这里没有混淆的余地:下面的 anint 除了 A 之外不能是其他的。

module A = struct
  type test = Graphics.status
end

module type ASIG = sig
  type test = A.test
  val atest : test 
end

module Func (H : ASIG) = struct
  let _ = let open H in atest.key 
end

但是,它提高了

Warning 40: key was selected from type Graphics.status.
It is not visible in the current scope, and will not 
be selected if the type becomes unknown.

如何在不禁用警告的情况下告诉它“很好”?

我知道我可以通过打开 A 来解决它。但是,如果 H 定义了自己的函数和类型,与 A 相似——但不等于——,那么它将产生不必要的冲突。我也知道我可以复制定义,但这违背了类型别名的目的,并且涉及大量不必要的代码重复。也许没有解决方案,但我想知道为什么 OCaml 在这个问题上如此愚蠢:类型别名应该也意味着构造函数和记录字段别名,不是吗?

【问题讨论】:

标签: ocaml warnings type-alias


【解决方案1】:

当引用key字段时,您可以在本地简单地打开模块定义原始类型,如下所示:

module A = struct
  type test = Graphics.status
end

module type ASIG = sig
  type test = A.test
  val atest : test 
end

module Func (H : ASIG) = struct
  let _ = let open H in atest.Graphics.key 
end

或者如果您需要参考几个字段:
let _ = let open H in Graphics.(atest.key, atest.button)

【讨论】:

    【解决方案2】:

    嗯,这是因为模块签名ASIG 需要查看test 类型的定义以实现A。这通常会导致类型的可见性出现问题,并且有时需要重复类型定义,其中合约满足实现而不是引用它。

    我们如何解决这个警告?在ASIG 中,我们不需要定义type test = A.test,而是像我们在实现中所做的那样显式地做type test = { anint: int },所以:

    module ASIG = sig
      type test = { anint: int }
      val atest : test
    end
    
    module A = struct
      type test = { anint: int }
    end
    
    module Func (H : ASIG) = struct
      let _ = let open H in atest.anint
    end
    

    H 模块将无法在其范围内查看anint,否则,因为签名具有链接到实现的类型(合同)。这也是 OCaml 哲学的核心概念,隔离签名和实现,避免签名依赖于实现。

    【讨论】:

    • 我是否可以滥用您的帮助并要求这种情况有用的情况,即对类型进行别名而不是其构造函数/字段?
    • 一般来说,当你不需要将类型的内部暴露给将要使用它的模块时,你可以只使用它的空定义。例如,如果您的Func 函子不必显式使用anint,那么ASIGtype test 的定义可能只是type test(这不会暴露它,我们保持抽象)。如果你这样做,你可以使用带有类型参数的模块。在您的示例中,test 可以是抽象的,H 可以是 ASIG with type test = A.test
    • OCaml 手册第 2 章详细讨论了模块系统、函子和模块的 with type(提供实现并避免重复):caml.inria.fr/pub/docs/manual-ocaml/moduleexamples.html
    • 好的,不是我真正需要的,但是谢谢。我将更新问题以显示更多我的问题。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-03-08
    • 1970-01-01
    • 2015-06-11
    • 1970-01-01
    • 2014-01-10
    • 2023-02-19
    • 2022-11-03
    相关资源
    最近更新 更多