如何解决OCaml:在 mli 文件中表达“t 集”
OCaml 的新手和 Sets 的绊脚石(真的,模块类型和函子)。我想在 .mli
文件中定义以下内容:
type t
type tag
val tags : t -> <set of tag>
其中 set of tag
是我无法弄清楚的类型,类似于 tag list
。
更新:感谢 Jeffrey Scofield 在下面提供的有用评论,但由于我的真正问题仍未得到解答,我认为我表达得不太好。这是第二次尝试:
鉴于此a.ml
:
type tag = string
module TagSet = Set.Make (struct
type t = tag
let compare = String.compare
end)
type t = { name : string; tags : TagSet.t }
let empty = { name = ""; tags = TagSet.empty }
let get_tags { tags; _ } = tags
如何填写此a.mli
?
type t
type tag
val empty : t
val get_tags : t -> ???
其中 ???
表示“TagSet.t”,同时仍然保持 tag
抽象,即“使用 t = tag
的 OrderedType 调用 Set.Make 的结果”。
这可能吗?似乎必须如此。我正在寻找 OCaml 与 Scala 的 Set[T]
最接近的东西。
解决方法
在开始探索 OCaml 的模块系统时,从编译器自己直接推断出的模块类型开始,逐步修改以更好地适应您的需求,这是非常有用的。
例如,从您的实现中推断出的模块是:
type tag = string
module TagSet :
sig
type elt = tag
type t
val empty : t
...
val add_seq : elt Seq.t -> t -> t
val of_seq : elt Seq.t -> t
end
type t = { name : tag; tags : TagSet.t; }
val empty : t
val get_tags : t -> TagSet.t
(您可以从 Merlin、ocaml-lsp、utop 或 ocamlc -i path_to_file.ml
中获取此推断模块类型)。
从这一点开始,我们可以删除信息使类型tag
和t
抽象:
type tag
type t
module TagSet :
sig
type elt = tag
type t
val empty : t
...
val add_seq : elt Seq.t -> t -> t
val of_seq : elt Seq.t -> t
end
val empty : t
val get_tags : t -> TagSet.t
然后另一个问题是 TagSet
的模块类型非常大且冗长。能够将此签名定义为具有 Set
类型元素的模块类型 tag
会很好。幸运的是,模块Set
定义了一个命名签名S
,正是出于这个原因,它描述了Make
结果的签名。如果我们使用这个预定义的签名,我们可以将之前的定义简化为
type tag
type t
module TagSet : Set.S with type elt = tag
val empty : t
val get_tags : t -> TagSet.t
,
您可以在接口中定义抽象参数化类型 'a set
:
type t
type tag
type 'a set
val tags : t -> tag set
当您编写 .ml 文件时,您必须确定 'a set
的表示和实现。即,您需要提供一个可以具有任何元素类型的集合。
你也可以只有两种抽象类型,一种用于标签,一种用于一组标签:
type t
type tag
type tagset
val tags : t -> tagset
当您为此编写 .ml 文件时,您只需要实现一组标记(这可能比一般设置更有效)。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。