我已经阅读了一些类似的问题和一些在线示例,但我仍然不知道在这种特殊情况下如何编写.mli
文件。
在我的项目中,我使用带有int键的通用映射模块,然后根据我想要存储的值来专门化。假设我想用它来存储对,所以我有一个这样的文件:
file 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
使用此子模块的文件是:
file useMap.ml:
open DataStr
let use k m =
IntMap.add k ((Random.int 6), (Random.int 8)) m
with interface:
file useMap.mli:
open DataStr
val use : int -> Couples.t -> Couples.t
到目前为止,非常好。
现在假设我要公开子模块Couples
,但不要显示int2couple
类型。然后我会写这个界面:
file dataStr.mli:
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
*)
问题是,如果我添加此接口,我会收到此编译错误:
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
有没有办法编写一个让我能做我想做的事情的界面,而不是评论中的“冗余”界面?
答案 0 :(得分:0)
如评论中所述,在实例化仿函数时,无法避免接口(mli文件)和实现(ml文件)之间的冗余。
您可以做的最好的事情如下:
$ cat dataStr.mli:
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
type int2couple = couple IntMap.t
module Couples = struct type t = int2couple end