Types 不同ocaml模块中的相同类型不';不匹配

Types 不同ocaml模块中的相同类型不';不匹配,types,module,ocaml,Types,Module,Ocaml,很抱歉,这看起来像一个“琐事”问题,但这是我能想到的最简单的例子: 模块类型Foo=sig a型t型 瓦尔·福:“a->”a t 终止 模块Foo:Foo=struct 类型“a t=t of”a 设foox=tx 终止 (*重写foo,添加一个函数*) 模块类型Bar=sig 包括Foo 值栏:int->int t 终止 模块栏:栏=结构 包括Foo 设bar n=foo(n+1) 终止 (*整型Baz的特殊化*) 模块类型Baz=sig t型 值栏:int->t 终止 模块Baz:Baz=s

很抱歉,这看起来像一个“琐事”问题,但这是我能想到的最简单的例子:

模块类型Foo=sig
a型t型
瓦尔·福:“a->”a t
终止
模块Foo:Foo=struct
类型“a t=t of”a
设foox=tx
终止
(*重写foo,添加一个函数*)
模块类型Bar=sig
包括Foo
值栏:int->int t
终止
模块栏:栏=结构
包括Foo
设bar n=foo(n+1)
终止
(*整型Baz的特殊化*)
模块类型Baz=sig
t型
值栏:int->t
终止
模块Baz:Baz=struct
类型t=int Foo.t
设bar=bar.bar
终止
在本例中,
Foo.t
Bar.t
是完全相同的类型。因此,
intfoo.t
intbar.t
相同

但是,我得到以下编译错误:

File "example.ml", lines 31-34, characters 19-3:
31 | ...................struct
32 |   type t = int Foo.t
33 |   let bar = Bar.bar
34 | end
Error: Signature mismatch:
       Modules do not match:
         sig type t = int Foo.t val bar : int -> int Bar.t end
       is not included in
         Baz
       Values do not match:
         val bar : int -> int Bar.t
       is not included in
         val bar : int -> t
       File "example.ml", line 28, characters 2-20: Expected declaration
       File "example.ml", line 33, characters 6-9: Actual declaration
如果我替换
类型t=int Foo.t
类型t=int Bar.t
,编译会突然匹配。在我的原始代码中,我有很多东西依赖于这两种类型。在我的例子中,这是一个从未编译过的:

模块类型Baz=sig
t型
val foo:int->t
值栏:int->t
终止
模块Baz:Baz=struct
类型t=int Foo.t
设foo n=foo.foo n
设bar=bar.bar
终止

我如何才能告诉编译程序
Foo.t
Bar.t
是相同的,而不使它们“公开可见”

在您的示例中
Foo.t
Bar.t
从类型检查器的角度来看是完全不相关的类型。的确,当你写作的时候

module Bar: Bar
您正在将模块
Bar
的类型严格限制为
Bar.t
。在模块类型
Bar
中,
Bar.t
是一种抽象类型,与任何其他类型没有任何已知关系

如果要保留与
Foo.t
相同的
Bar.t
信息,则需要在模块类型约束中重新添加此信息:

module Bar : Bar with type 'a t = 'a Foo.t
通常,当您开始在OCaml中编写模块类型时,最好从类型检查器推断的模块类型开始,并且只以节省的方式删除信息。否则,人们通常使用完全不透明的模块类型来约束模块,这些模块类型会从模块中删除大量信息,从而使模块变得无用

比如说,用你的简化定义

module type Foo = sig
  type 'a t
  val foo : 'a -> 'a t
end

module Foo : Foo = struct
  type 'a t = T of 'a
  let foo x = T x
end

模块
Foo
基本上是无用的,因为您有一个黑盒类型的构造函数
Foo.t
,您只能为其创建此类型的值,但决不能销毁或使用它们。

在您的示例中
Foo.t
Bar.t
从类型检查器的角度来看是完全不相关的类型。的确,当你写作的时候

module Bar: Bar
您正在将模块
Bar
的类型严格限制为
Bar.t
。在模块类型
Bar
中,
Bar.t
是一种抽象类型,与任何其他类型没有任何已知关系

如果要保留与
Foo.t
相同的
Bar.t
信息,则需要在模块类型约束中重新添加此信息:

module Bar : Bar with type 'a t = 'a Foo.t
通常,当您开始在OCaml中编写模块类型时,最好从类型检查器推断的模块类型开始,并且只以节省的方式删除信息。否则,人们通常使用完全不透明的模块类型来约束模块,这些模块类型会从模块中删除大量信息,从而使模块变得无用

比如说,用你的简化定义

module type Foo = sig
  type 'a t
  val foo : 'a -> 'a t
end

module Foo : Foo = struct
  type 'a t = T of 'a
  let foo x = T x
end

模块
Foo
基本上是无用的,因为您有一个黑盒类型构造函数
Foo.t
,您只能为其创建此类型的值,但不能销毁或使用它们。

您能否扩展到“更好地从类型检查器推断的模块类型开始?”例如,对于实现您的建议的最后一个代码段,您建议进行哪些具体更改?(=如果删除
:Foo
注释,类型检查器将推断模块的最通用模块类型:
模块类型Foo=sig type'a t=t of'a val Foo:'a->'a t end
。如果从该模块类型开始,您可以问自己我可以从该签名中删除哪些信息。在这种情况下,答案是零。Ma我建议你问一个单独的问题,如果你想问一个更详尽的问题,关于在模块类型中抽象类型什么时候有意义?啊,我以为你说的是一些使用特殊编译器标志的过程/习惯用法,而不是简单地忽略类型约束。我的错!你能继续吗“最好从类型检查器推断的模块类型开始?”例如,对于实现您的建议的最后一个代码段,您建议进行哪些具体更改?(=如果删除
:Foo
注释,类型检查器将推断模块的最通用模块类型:
模块类型Foo=sig type'a t=t of'a val Foo:'a->'a t end
。如果从该模块类型开始,您可以问自己我可以从该签名中删除哪些信息。在这种情况下,答案是零。Ma我建议你问一个单独的问题,如果你想问一个更详尽的问题,什么时候在模块类型中抽象类型是有意义的?啊,我以为你说的是一些使用特殊编译器标志的过程/习惯用法,而不是简单地忽略类型约束。我的错!