在Ocaml中键入的一个奇怪示例

在Ocaml中键入的一个奇怪示例,ocaml,typing,Ocaml,Typing,非常奇怪的是,这个ocaml代码段是由顶级输入的。看看结构,如果g的类型为int->int,如顶层所示,那么结构的hx=gx部分将无法获得统一的类型。那么,有人能澄清一下吗 module Mymodule : sig val h:int ->int val g: string-> string end = struct let g x = x let h x = g x end 这是topelevel的回应: module Mymodule : sig val

非常奇怪的是,这个ocaml代码段是由顶级输入的。看看结构,如果g的类型为int->int,如顶层所示,那么结构的
hx=gx
部分将无法获得统一的类型。那么,有人能澄清一下吗

module Mymodule : sig
  val h:int ->int
  val g: string-> string
end = struct
  let g x = x
  let h x = g x
end
这是topelevel的回应:

  module Mymodule : sig val h : int -> int val g : string -> string end

我想说的是,
string->string
类型在导出之前不会应用于
g
来自模块。在模块内部(因为您没有给它类型),它具有
'a->'a
。(免责声明:我不是一名模块专家,但我正在努力学习。)

这里需要了解的重要一点是,OCaml以组合方式执行类型推断,即,它将首先推断
结构的类型。。。结束
,然后它将根据信号匹配推断的类型。。。结束以验证结构是否确实实现了签名

例如,如果你写

module Monkey : sig val f : int -> int end =
struct
  let f x = x
end 
然后OCaml会很高兴,因为它将看到
f
有一个多态类型
'a->'a
,可以专门化为所需的类型
int->int
。因为
sig。。。end
使
Monkey
不透明,即签名隐藏了实现,它将告诉您
f
具有类型
int->int
,即使实际实现具有多态类型

在您的特定情况下,OCaml首先推断
g
的类型为
'a->'a
,然后
h
的类型也是
'a->'a
。因此得出结论,该结构具有

sig val g : 'a -> 'a val h : 'a -> 'a end
接下来,将签名与给定签名进行匹配。因为类型为
'a->'a
的函数可以专用于
int->int
以及
string->string
的函数,OCaml得出的结论是一切正常。当然,使用
sig的整个要点。。。end
是为了使结构不透明(实现是隐藏的),这就是toplevel不公开多态类型
g
h
的原因

下面是显示OCaml工作原理的另一个示例:

module Cow =
struct
  let f x = x
  let g x = f [x]
  let a = f "hi"
end

module Bull : sig
  val f : int -> int
  val g : 'b * 'c -> ('b * 'c) list
  val a : string
end = Cow
答案是

module Cow :
    sig 
      val f : 'a -> 'a
      val g : 'a -> 'a list
      val a : string
    end

module Bull :
    sig
      val f : int -> int
      val g : 'a * 'b -> ('a * 'b) list
      val a : string end
    end