4

我想将我的一些类型转换为使用 Ocaml 多态变体,将它们分解为开放递归,同时仍然保留我现有的私有非多态类型的执行,以及对模式匹配的详尽检查。

我的产品是一个编译器,因此类型集由各种算法更改,目前我必须包含所有构造函数,其中不应该出现“断言错误”的构造函数。

我应该补充一点,我曾经使用多态变体,但切换回普通变体,因为类型推断不能很好地与多态变体一起使用:错误消息很难阅读,而且它们比通常的错误推断错误得多,需要参数上的更多类型注释以保持任何理智。问题是没有它们,私有构造函数的执行很强大,但客户端算法的执行很弱。

我不确定将构造函数的“临时”子集与隐私相结合是否可能或实用。关于它的实用性有什么建议吗?

编辑:简单的示例类型:

(* open *)
type 'a x' = [`A | `B of 'a]

(* closed *)
type x = private 'u x' as 'u

(* open extension *)
type 'a y' = ['a x' | `C of 'a] 

(* closed extension *)
type y = private 'u y' as 'u 

let mkA () = `A
let mkB' (a:'a x') = `B a

(* how to do this? *)
let mkB (a:x) = mkB' (a :> 'a x')

使用开放递归,构造函数必须遵循类型的打开/关闭模式。客户只会看到封闭的版本。这意味着,与我当前的系统中单个构造函数就足够了,我现在需要一个用于每个封闭类型,每个包含构造函数的类型。

即使我能弄清楚如何做到这一点,如果你说 6 个相互依赖的类型都使用开放递归,这会导致可能的组合呈指数爆炸式增长,这也很难,但目前尚不清楚这是否是一个优势接受运行时检查。我花了大约 2 个小时来添加一个新的构造函数,因为每个模式匹配都会因穷举错误而失败,并且必须修复......即使新的构造函数在编译的那个阶段没有用。

4

1 回答 1

1

私有多态变体只对模块和接口感兴趣。由于接口,它们在模块中是公共的,但在外部是私有的。如果您希望在模块之外访问公共表示,那么您必须提供执行此操作的功能:

module M : sig
  (* open *)
  type 'a x' = [`A | `B of 'a]
  (* closed *)
  type x = private 'u x' as 'u
  val f: x -> x x'
end = struct
  type 'a x' = [`A | `B of 'a]
  type x = 'u x' as 'u
  let f a = a
end

另一种方法是更改​​您的类型,仅将头构造函数设为私有:

(* open *)
type 'a x' = [`A | `B of 'a]
(* closed *)
type x = 'u x' as 'u
(* private *)
type px = private x
let f (a: px) = (a :> x)
于 2018-09-07T14:07:32.027 回答