Dictionary 使用.mli文件和映射

Dictionary 使用.mli文件和映射,dictionary,types,interface,ocaml,Dictionary,Types,Interface,Ocaml,我读过一些类似的问题和一些在线示例,但在这种情况下,我仍然不知道如何编写.mli文件 在我的项目中,我使用一个带有int键的通用映射模块,然后根据要存储的值对其进行专门化。假设我想用它来存储配对,所以我有一个如下文件: 文件dataStr.ml: module IntOrder = struct type t = int let compare = Pervasives.compare end module IntMap = Map.Make( IntOrd

我读过一些类似的问题和一些在线示例,但在这种情况下,我仍然不知道如何编写
.mli
文件

在我的项目中,我使用一个带有int键的通用映射模块,然后根据要存储的值对其进行专门化。假设我想用它来存储配对,所以我有一个如下文件:

文件dataStr.ml:

module IntOrder =
   struct
      type t = int
      let compare = Pervasives.compare
   end

module IntMap = Map.Make( IntOrder )

type couple = int * int
(* pretty names *)
type int2couple = couple IntMap.t
module Couples = struct type t = int2couple end
open DataStr

let use k m =
   IntMap.add k ((Random.int 6), (Random.int 8)) m
module IntOrder =
  struct
      type t = int
      let compare = Pervasives.compare
  end

module IntMap = Map.Make( IntOrder )

type couple = int * int
type int2couple = couple IntMap.t
module Couples = struct type t = int2couple end
使用此子模块的文件将是:

文件useMap.ml:

module IntOrder =
   struct
      type t = int
      let compare = Pervasives.compare
   end

module IntMap = Map.Make( IntOrder )

type couple = int * int
(* pretty names *)
type int2couple = couple IntMap.t
module Couples = struct type t = int2couple end
open DataStr

let use k m =
   IntMap.add k ((Random.int 6), (Random.int 8)) m
module IntOrder =
  struct
      type t = int
      let compare = Pervasives.compare
  end

module IntMap = Map.Make( IntOrder )

type couple = int * int
type int2couple = couple IntMap.t
module Couples = struct type t = int2couple end
带接口:

文件useMap.mli:

open DataStr

val use : int -> Couples.t -> Couples.t
module IntMap : Map.S with type key = int

module Couples : sig type t end
(*
I'd like to avoid the redundancy of using
module Couples : sig type t = (int * int) IntMap.t end
*)
module IntMap : Map.S with type key = int
type couple = int * int
type int2couple = couple IntMap.t
module Couples : sig type t = int2couple end
到目前为止,一切顺利

现在假设我想公开子模块
耦合
,但不想输入
int2couple
。然后我将编写此接口:

文件dataStr.mli:

open DataStr

val use : int -> Couples.t -> Couples.t
module IntMap : Map.S with type key = int

module Couples : sig type t end
(*
I'd like to avoid the redundancy of using
module Couples : sig type t = (int * int) IntMap.t end
*)
module IntMap : Map.S with type key = int
type couple = int * int
type int2couple = couple IntMap.t
module Couples : sig type t = int2couple end
问题是,如果我添加了此接口,则会出现以下编译错误:

Error: The implementation useMap.ml does not match the interface useMap.cmi:
       Values do not match:
         val use :
           DataStr.IntMap.key ->
           (int * int) DataStr.IntMap.t -> (int * int) DataStr.IntMap.t
       is not included in
         val use : int -> DataStr.Couples.t -> DataStr.Couples.t

除了注释中的“冗余”接口之外,还有什么方法可以编写一个接口让我做我想做的事情吗?

如注释中所述,在实例化函子时,无法避免接口(mli文件)和实现(ml文件)之间的冗余

您所能做的最好工作如下:

$cat dataStr.mli:

open DataStr

val use : int -> Couples.t -> Couples.t
module IntMap : Map.S with type key = int

module Couples : sig type t end
(*
I'd like to avoid the redundancy of using
module Couples : sig type t = (int * int) IntMap.t end
*)
module IntMap : Map.S with type key = int
type couple = int * int
type int2couple = couple IntMap.t
module Couples : sig type t = int2couple end
$cat dataStr.ml:

module IntOrder =
   struct
      type t = int
      let compare = Pervasives.compare
   end

module IntMap = Map.Make( IntOrder )

type couple = int * int
(* pretty names *)
type int2couple = couple IntMap.t
module Couples = struct type t = int2couple end
open DataStr

let use k m =
   IntMap.add k ((Random.int 6), (Random.int 8)) m
module IntOrder =
  struct
      type t = int
      let compare = Pervasives.compare
  end

module IntMap = Map.Make( IntOrder )

type couple = int * int
type int2couple = couple IntMap.t
module Couples = struct type t = int2couple end

如果您封装类型
(int*int)IntMap.t
,就无法知道在
DataStr
之外,它实际上是一个映射。我猜这种封装级别并没有实现多少功能。您想在客户端代码中隐藏什么?我只想显示“耦合”,同时隐藏“int2couple”和可能的“耦合”,因为我创建它们只是为了使用它们
dataStr.ml
。除了接口可读性之外,对于我试图获得的内容没有什么特别的原因。在这种情况下,您可以公开
module coups=struct type t=(int*int)IntMap.t end
。是的,正如我所写的,我希望避免在定义(
dataStr.ml
)和接口中重复类似
(int*int)IntMap.t
的语句(
dataStr.mli
),但我想这是唯一的选择。它仍然让我写“更简单”使用这些类型映射的文件接口,如
val use:int->Couples.t->Couples.t
。如果您愿意,可以将您的注释合并到一个答案中,我会将其标记为最佳。我真的不相信会出现其他解决方案。谢谢您的建议!