我想在几个模块中撰写几个“特征”。函数可能需要多个这样的“特征”作为其输入,即:
type 'a x_t = < get_x : int ; .. > as 'a constraint 'a = < get_b : float ; .. >
val foo : x_t -> float
在界面中手动编写这些特征既麻烦又容易出错,但完全可能。
但在一个理想的世界中,我应该能够使用“特征”的名称,而不是手动编写所有必需的字段,即写下如下内容:
type 'a x_t = < get_x : int ; .. > as 'a constraint 'a <: a_t
不幸的是,OCaml语法不允许这样做。这个似乎是一个纯粹的语法限制,所以我想知道是否有更深层次的原因?
换句话说:为什么我不能直接在OCaml类型签名中编写子类型约束?
编辑:澄清用例:我有几个(有时是相互依赖的)模块,它们提供某些常见共享状态的功能。这些模块应该是可组合的并且松散耦合(即,只需要它们的全局状态部分来满足它们的需要,因此,我总是可以用新的功能扩展状态)。为了达到这个目的,将状态封装在一个提供多个镜头的物体中(上面我只使用了吸气剂,而不是定位器)。因此,如果我为模块提供接口定义,我需要通过对编码整个状态类型的类型参数的约束来描述我的函数签名中所需的镜头。现在我正在寻找一种方法来编写这些组合的签名要求尽可能简短和可读。
答案 0 :(得分:8)
如果将特征定义为类类型而不是对象类型,则可以使用#foo
语法。
class type b = object
method get_b : float
end
class type c = object
method get_c : bool
end
type 'a x_t = < .. > as 'a
constraint 'a = #b
constraint 'a = #c
您还可以通过继承机制撰写特征:
class type e = object
inherit b inherit c
end
(看起来类型太聪明了,但为什么不试验......)