OCaml - 来自类型别名的混淆(警告40)

时间:2018-04-13 14:24:17

标签: ocaml warnings type-alias

我不明白为什么OCaml无法弄清楚这里没有混淆的空间:下面的aint不能是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在这个上如此盲目愚蠢:类型别名应该也意味着构造函数和记录字段别名,不应该吗?

2 个答案:

答案 0 :(得分:5)

您可以在引用字段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)

答案 1 :(得分:1)

嗯,这是因为模块签名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哲学的核心概念,它隔离了签名和实现,并根据实现避免了签名。