我想设计2个模块A
和B
,它们都有自己的功能,例如:A.compare: A.t -> A.t -> bool
,B.compare: B.t -> B.t -> bool
。 A
和B
的元素是可转换的。所以我还需要函数a_of_b : B.t -> A.t
和b_of_a : A.t -> B.t
。我的问题是我应该在哪里定义这些功能?在A
或B
或其他地方的结构内部?
有人可以帮忙吗?
Edit1:刚刚修改了一些基于第一条评论的错误
答案 0 :(得分:1)
您可能意味着A.compare: A.t -> A.t -> bool
因为类型较小。
您可以拥有一个单独的模块AB,其中包含A的类型和B的类型。
您可以拥有包含A& A的单个模块AB。 B作为子模块。
您也可以使用recursive modules&函子。
答案 1 :(得分:1)
这是一个经典的设计问题。在OOP语言中,很难优雅地解决这个问题,因为类封装了类型定义和与该类型相关的方法。因此,只要你有一个像a_of_b这样的函数,它将两种类型视为相同的范围,就没有明确的位置。
OCaml正确地为这些不同的需求提供了不同的语言机制:使用关键字type
引入类型定义,并在module
中收集相关方法。这为您设计API提供了更大的灵活性,但并未自动解决问题。
一种可能性是定义模块A和B,两者都有各自的类型和比较功能。然后,剩下的问题是放置a_of_b
和b_of_a
的位置。您可以任意优先考虑模块A,并定义函数A.to_b
和A.of_b
。这就是标准库在将to_list
和of_list
放入Array时所执行的操作。这缺乏对称性;没有理由不将这些功能放在B中。
相反,您可以使用of_
函数与to_
函数进行标准化。假设你更喜欢to_
。然后,您将定义函数A.to_b
和B.to_a
。现在的问题是模块A和B是相互依赖的,只有在同一个文件中定义它们才能实现。
如果您将有许多处理类型A.t
和B.t
的值的函数,那么可能值得定义模块AB,并将所有这些函数放在那里。如果你只需要两个,那么额外的模块可能有点过分。
另一方面,如果关于A和B的函数总数很小,则只能使用type a
,type b
以及所有相关方法创建模块AB。但是,这并不遵循OCaml社区在其自己的模块中命名类型t
的惯例,并且将Set和Map仿函数应用于这些类型将更加困难。