6

很奇怪,这个 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

这是顶层的回应:

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

2 回答 2

8

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

于 2012-06-19T17:01:37.923 回答
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有 type int -> int,即使实际的实现有一个多态类型。

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

sig val g : 'a -> 'a val h : 'a -> 'a end

接下来,将签名与给定的签名进行匹配。因为类型的函数'a -> 'a可以被专门化int -> intstring -> stringOCaml 得出的结论是一切都很好。当然,使用的全部意义sig ... end在于使结构不透明(实现是隐藏的),这就是为什么顶层不暴露and 的多态类型的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
于 2012-06-19T21:03:19.463 回答