Ocaml 如何在两组不同(但重叠)和类型之间进行集合并集
我正在为编译器实现 以下是第一个集合和后续集合元素的类型定义:Ocaml 如何在两组不同(但重叠)和类型之间进行集合并集,ocaml,Ocaml,我正在为编译器实现 以下是第一个集合和后续集合元素的类型定义: type first_set_element = | Terminal of terminal | Epsilon [@@deriving show, sexp] type follow_set_element = | Terminal of terminal | EndSymbol [@@deriving show, sexp] 如您所见,“终端”是两者之间的重叠变体 我希望能够得到一个FollowSet和一
type first_set_element =
| Terminal of terminal
| Epsilon [@@deriving show, sexp]
type follow_set_element =
| Terminal of terminal
| EndSymbol [@@deriving show, sexp]
如您所见,“终端”是两者之间的重叠变体
我希望能够得到一个FollowSet和一个FirstSet的并集,然后减去FirstSet的ε,这样结果仍然是FollowSet
当然,“简单”的解决方案是编写一个函数,将第一个集合转换为FollowSet,然后使用FollowSet.union
。理想情况下,我将能够不重新实现集合操作。我很好奇OCaml类型系统中是否有什么东西,或者是否有更好的设计来解决这个问题
可能就是我要找的
以下是我如何定义集合:
module FirstSetElement = struct
type t = first_set_element
let compare a b = match (a, b) with
| (Terminal(a), Terminal(b)) -> String.compare a b
| (Terminal(_), Epsilon) -> 1
| (Epsilon, Terminal(_)) -> -1
| (Epsilon, Epsilon) -> 0
let sexp_of_t t = sexp_of_first_set_element t
let t_of_sexp t = first_set_element_of_sexp t
end
module FirstSet = Set.Make(FirstSetElement)
module FollowSetElement = struct
type t = follow_set_element
let compare a b = match (a, b) with
| (Terminal(a), Terminal(b)) -> String.compare a b
| (Terminal(_), EndSymbol) -> 1
| (EndSymbol, Terminal(_)) -> -1
| (EndSymbol, EndSymbol) -> 0
let sexp_of_t t = sexp_of_follow_set_element t
let t_of_sexp t = follow_set_element_of_sexp t
end
module FollowSet = Set.Make(FollowSetElement)
是的,多态变体有帮助。他们正是为了完成这样的任务。 下面是一个简单的例子:
a型=
[`A
|`Shared of int]
b型=
[`B
|`Shared of int]
设a=[`a;`Shared 1]
(*a:-[>`a |`Shared of int]list*)
设b=[`b;`Shared 2]
(*b:-[>`b |`Shared of int]list*)
设c=a@b
(*c:-[>`A |`B |`Shared of int]list*)
您可以通读手册以了解更多详细信息。
主要缺点是,您会得到更详细的类型,如上所示。如果它们的形状和行为完全相同,为什么它们会不同?它只是为
Epsilon
/EndSymbol
构造函数提供一个更有意义的名称吗?如果是这样的话,我会说你应该把数据结构抽象出来。使用公共数据结构,但将其隐藏并公开显式构造函数和操作。