Module OCaml使用在函子外部定义的签名来限制生成模块的可见性

Module OCaml使用在函子外部定义的签名来限制生成模块的可见性,module,ocaml,encapsulation,functor,Module,Ocaml,Encapsulation,Functor,我正试图编写一个函子,它接受一对有序的事物,并生成另一个有序的事物(按照字典定义的顺序) 但是,我希望得到的“有序类型”是抽象的,而不是OCaml元组 使用内联/匿名签名很容易做到这一点 (* orderedPairSetInlineSig.ml *) module type ORDERED_TYPE = sig type t val compare : t -> t -> int end module MakeOrderedPairSet (X : ORDERED_TY

我正试图编写一个函子,它接受一对有序的事物,并生成另一个有序的事物(按照字典定义的顺序)

但是,我希望得到的“有序类型”是抽象的,而不是OCaml元组

使用内联/匿名签名很容易做到这一点

(* orderedPairSetInlineSig.ml *)

module type ORDERED_TYPE = sig
  type t
  val compare : t -> t -> int
end

module MakeOrderedPairSet (X : ORDERED_TYPE) :
  sig
    type t
    val get_fst : t -> X.t
    val get_snd : t -> X.t
    val make : X.t -> X.t -> t
    val compare : t -> t -> int
  end = struct
    type t = X.t * X.t

    let combine_comparisons fst snd =
      if fst = 0 then snd else fst

    let compare (x, y) (a, b) =
      let cmp  = X.compare x a in
      let cmp' = X.compare y b in
      combine_comparisons cmp cmp'

    let get_fst ((x, y) : t) = x

    let get_snd ((x, y) : t) = y

    let make x y = (x, y)
  end
我想给我的匿名签名起一个类似于
ORDERED\u PAIR\u SET\u TYPE
的名字,并将其移到
MakeOrderedPairSet
的定义之外,就像这样(警告:语法无效):

在签名中,
el
是一个抽象类型,我试图在
MakeOrderedPairSet
的主体内绑定到
X.t

然而,我不知道如何把所有的东西组合在一起

(ORDERED\u PAIR\u SET\u TYPE with TYPE el=X.t)
是我能想到的最明显的表达方式,“给我一个与此类似的签名,但用一个具体的类型替换了一个抽象类型(或者在本例中是不同的抽象类型)”。但是,在这种情况下,它在语法上是无效的(因为有括号)。去掉括号也不会产生有效的“模块语言级表达式”;我开着它是因为我觉得它让我的意图更加明显


所以。。。如何使用命名签名来限制[functor生成的模块]/[parameterized module]的可见性?

如果不想将
el
添加到模块的导出中,则有两种方法:

  • 使用替换约束:

    el:=X.t类型的有序\u对\u集\u类型
    
    这将从签名中删除
    el
    的规范

  • (* orderedPairSetInlineSig.ml *)
    
    module type ORDERED_TYPE = sig
      type t
      val compare : t -> t -> int
    end
    
    module MakeOrderedPairSet (X : ORDERED_TYPE) :
      sig
        type t
        val get_fst : t -> X.t
        val get_snd : t -> X.t
        val make : X.t -> X.t -> t
        val compare : t -> t -> int
      end = struct
        type t = X.t * X.t
    
        let combine_comparisons fst snd =
          if fst = 0 then snd else fst
    
        let compare (x, y) (a, b) =
          let cmp  = X.compare x a in
          let cmp' = X.compare y b in
          combine_comparisons cmp cmp'
    
        let get_fst ((x, y) : t) = x
    
        let get_snd ((x, y) : t) = y
    
        let make x y = (x, y)
      end
    
  • 使用参数化签名。不幸的是,这在OCaml中无法直接表达,但需要围绕签名的定义进行一些额外的函子练习:

    模块集\类型(X:有序\类型)=
    结构
    模块类型S=
    信号
    t型
    val get_fst:t->X.el
    val get_snd:t->X.el
    val make:X.el->X.el->t
    val比较:t->t->int
    结束
    结束
    
    有了这些,你可以写:

    模块MakeOrderedPairSet(X:ORDERED类型):SET类型(X).S=。。。
    

  • 如果您不想将
    el
    添加到模块的导出中,则有两种方法:

  • 使用替换约束:

    el:=X.t类型的有序\u对\u集\u类型
    
    这将从签名中删除
    el
    的规范

  • (* orderedPairSetInlineSig.ml *)
    
    module type ORDERED_TYPE = sig
      type t
      val compare : t -> t -> int
    end
    
    module MakeOrderedPairSet (X : ORDERED_TYPE) :
      sig
        type t
        val get_fst : t -> X.t
        val get_snd : t -> X.t
        val make : X.t -> X.t -> t
        val compare : t -> t -> int
      end = struct
        type t = X.t * X.t
    
        let combine_comparisons fst snd =
          if fst = 0 then snd else fst
    
        let compare (x, y) (a, b) =
          let cmp  = X.compare x a in
          let cmp' = X.compare y b in
          combine_comparisons cmp cmp'
    
        let get_fst ((x, y) : t) = x
    
        let get_snd ((x, y) : t) = y
    
        let make x y = (x, y)
      end
    
  • 使用参数化签名。不幸的是,这在OCaml中无法直接表达,但需要围绕签名的定义进行一些额外的函子练习:

    模块集\类型(X:有序\类型)=
    结构
    模块类型S=
    信号
    t型
    val get_fst:t->X.el
    val get_snd:t->X.el
    val make:X.el->X.el->t
    val比较:t->t->int
    结束
    结束
    
    有了这些,你可以写:

    模块MakeOrderedPairSet(X:ORDERED类型):SET类型(X).S=。。。
    

  • 一旦缺少定义
    type el=X.t
    的问题得到解决,你的例子对我来说很有用(有括号和没有括号)?@octachron是。。。将显式的
    类型el=X.t
    添加到方法体中确实会使OCaml程序有效,但它也会将新导出的类型添加到接口中。。。因此,这并不完全等同于将第一个示例中的匿名接口“移动”到函子定义之外。一旦缺少定义
    type el=X.t
    的问题得到解决,您的示例对我有效(带括号和不带括号)?@octachron是的。。。将显式的
    类型el=X.t
    添加到方法体中确实会使OCaml程序有效,但它也会将新导出的类型添加到接口中。。。因此,它并不完全等同于在第一个示例中将匿名接口“移动”到函子定义之外。。。这是否意味着您可以在SML中编写参数化签名,而无需使用包装器模块?不,SML根本没有这种能力(尽管某些SML方言允许您编写类似于上述的内容)。为了进行比较。。。这是否意味着您可以在SML中编写参数化签名而无需使用包装器模块?不,SML根本没有这种能力(尽管某些SML方言允许您编写类似于上述内容的内容)。