OCaml - 来自类型别名的混淆(警告 40)
OCaml - confusion from type alias (warning 40)
我不明白为什么 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.
如何在不禁用警告的情况下告诉它"it's fine"?
我知道我可以通过打开 A
来解决它。但是,如果 H 定义了自己的函数和类型类似于——但不等于——A,那么它将产生不必要的冲突。我也知道我可以复制定义,但这违背了类型别名的目的,并且涉及很多不必要的代码重复。也许没有解决方案,但我想知道为什么 OCaml 在这个问题上如此愚蠢:类型别名应该也意味着构造函数和记录字段别名,不是吗?
嗯,发生这种情况是因为模块签名 ASIG
需要查看类型 test
的定义以实现 A
。这通常会导致类型的可见性出现问题,有时需要重复类型定义,其中合同满足实现而不是引用它。
我们如何解决这个警告?在 ASIG
中,我们需要像在实现中那样明确地做 type test = { anint: int }
,而不是定义 type test = A.test
,所以:
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 哲学的核心概念,即隔离签名和实现并避免签名依赖于实现。
您可以在引用字段 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)
我不明白为什么 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.
如何在不禁用警告的情况下告诉它"it's fine"?
我知道我可以通过打开 A
来解决它。但是,如果 H 定义了自己的函数和类型类似于——但不等于——A,那么它将产生不必要的冲突。我也知道我可以复制定义,但这违背了类型别名的目的,并且涉及很多不必要的代码重复。也许没有解决方案,但我想知道为什么 OCaml 在这个问题上如此愚蠢:类型别名应该也意味着构造函数和记录字段别名,不是吗?
嗯,发生这种情况是因为模块签名 ASIG
需要查看类型 test
的定义以实现 A
。这通常会导致类型的可见性出现问题,有时需要重复类型定义,其中合同满足实现而不是引用它。
我们如何解决这个警告?在 ASIG
中,我们需要像在实现中那样明确地做 type test = { anint: int }
,而不是定义 type test = A.test
,所以:
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 哲学的核心概念,即隔离签名和实现并避免签名依赖于实现。
您可以在引用字段 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)