Types 使OCaml模块签名显示其类型

Types 使OCaml模块签名显示其类型,types,module,ocaml,Types,Module,Ocaml,我举了以下例子: 模块类型S=sig t型 val do_something:t->unit 终止 模块Foo:S=struct 类型t=[`Foo of int |`Bar of string] 让我们做点什么吧 终止 模块Baz:S=struct 类型t=[`Baz of char |`Qux of unit] 让我们做点什么吧 终止 让= Foo.do_something`Foo 1; 做点什么 但运行此示例时,我得到: File "./m.ml", line 21, characters

我举了以下例子:

模块类型S=sig t型 val do_something:t->unit 终止 模块Foo:S=struct 类型t=[`Foo of int |`Bar of string] 让我们做点什么吧 终止 模块Baz:S=struct 类型t=[`Baz of char |`Qux of unit] 让我们做点什么吧 终止 让= Foo.do_something`Foo 1; 做点什么 但运行此示例时,我得到:

File "./m.ml", line 21, characters 19-27:
Error: This expression has type [> `Foo of int ]
       but an expression was expected of type Foo.t
基本上,根据我的理解。使它显化的可能是定义它。例如,类型t=某物

但问题是这种类型在Foo和Bar之间发生了变化


有没有一种方法可以在不知道其值的情况下使S.t在其签名中显化?

我认为,让界面根据使用情况来定义其他东西会有点违背使用共享界面的目的。然而,在某种意义上,您可以通过向签名添加类型约束来扩展签名,例如,类型为t=。。。。延长的签名也将与原件保持一致

以下是使用类型约束编译的示例:

module type S = sig
  type t

  val do_something : t -> unit
end

module Foo : S with type t = [`Foo of int | `Bar of string] = struct
  type t = [`Foo of int | `Bar of string]

  let do_something _ = ()
end

module Baz : S with type t = [`Baz of char | `Qux of unit] = struct
  type t = [`Baz of char | `Qux of unit]

  let do_something _ = ()
end


let () =
  Foo.do_something (`Foo 1);
  Baz.do_something (`Qux ())

问题确实在于签名约束

module Baz : S = struct
  type t = [`Baz of char | `Qux of unit]
  let do_something _ = ()
end
使类型Baz.t抽象。此外,这使得模块Baz变得无用,因为没有办法生成Baz.t类型的值

最简单的解决方案是删除签名约束。如果您记得签名约束只删除信息,并且模块的类型是结构化的,那么这就不那么令人惊讶了。特别是,这意味着

 module Do_twice(X:S) = struct
   let do_twice x = X.do_something x; X.do_something x
 end
 module Baz = struct
   type t = [`Baz of char | `Qux of unit]
   let do_something _ = ()
 end
 module Twice_Baz= Do_twice(Baz)
 let () = Twice_Baz.do_twice (`Baz 'a')
一切正常

如果希望有显式签名约束,则需要小心不要删除任何有用的信息。正确的方法是在带有with约束的模块类型S中添加关于类型t的更多信息:

 module Baz: S with type t = [`Baz of char | `Qux of unit]  = struct
   type t = [`Baz of char | `Qux of unit]
   let do_something _ = ()
 end