如何使Ocaml多态变体私有化

问题描述 投票:3回答:1

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

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

我应该添加我曾经使用的多态变体,但切换回普通变体,因为类型推断不适合多态变体:错误消息难以阅读,并且它们比通常的不良推论错误更多,需要一个更多类型的参数注释,以保持任何理智。问题是没有它们,私有构造函数的强制执行力很强,但客户端算法的执行力很弱。

我不确定将构造函数的“ad hoc”子集与隐私结合起来是否可行或可行。有什么实际可行的建议吗?

编辑:简单的示例类型:

(* 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个小时,因为每个模式匹配都会因详尽错误而失败并且必须修复。即使新构造函数在编译阶段没有用处。

ocaml polymorphic-variants
1个回答
0
投票

私有多态变体只对模块和接口很有用。它们在模块中是puclic,但由于界面,私人外部。如果您希望模块外部有权访问公共表示,那么您必须提供以下功能:

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)
© www.soinside.com 2019 - 2024. All rights reserved.