键入Ocaml的一个奇怪的例子

时间:2012-06-19 16:12:19

标签: ocaml typing

这个ocaml片段很好地被顶层打字,这很奇怪。查看结构,如果g的类型为int-> int,如顶层所示,则结构的h x = g x部分将无法进行类型统一。那么任何人都可以澄清一下吗?

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

2 个答案:

答案 0 :(得分:8)

我要说string -> string输入在导出之前不会应用于g 来自模块。在模块内部(因为你没有给它一个类型)它有类型 'a -> 'a。 (免责声明:我不是模块专家,试图学习。)

答案 1 :(得分:8)

这里要理解的重要一点是,OCaml以组合方式执行类型推断,即它首先会推断struct ... end的类型,然后它将匹配推断的类型与sig ... end进行验证该结构确实实现了签名。

例如,如果你写

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的重点是使结构不透明(实现是隐藏的),这就是为什么顶层暴露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