Ocaml (可选)将额外数据附加到类型
假设我有一个带有一系列递归类型声明的模块,并且已经有大量的使用者执行Ocaml (可选)将额外数据附加到类型,ocaml,Ocaml,假设我有一个带有一系列递归类型声明的模块,并且已经有大量的使用者执行打开M,然后使用类型1、类型2和类型3 module M = struct type type1 = | T1_Case1 of string * type2 | T1_Case2 of type3 and type2 = type3 list and type3 = | T3_Case1 of type1 | T3_Case2 of int end 在其中一个处理步骤中,需要将
打开M
,然后使用类型1
、类型2
和类型3
module M = struct
type type1 =
| T1_Case1 of string * type2
| T1_Case2 of type3
and type2 = type3 list
and type3 =
| T3_Case1 of type1
| T3_Case2 of int
end
在其中一个处理步骤中,需要将这些类型中的一个或多个扩展为添加了一些额外数据的类型,类似于:
type type1 =
| T1_Case1 of string * type2
| T1_Case2 of type3
and type2 = type3 list
and type3_ =
| T3_Case1 of type1
| T3_Case2 of int
and type3 = extra_data * type3_
是否有可能在不涉及外部codegen工具或破坏现有代码的情况下实现这一点
后一个选项排除了将M
转换为注释类型参数化的函子的可能性:
(* won't work since all places that used to deal with type3 should be updated *)
module type AnnotationT = sig type t end
module M_F(Annotation: AnnotationT) = struct
type type1 =
| T1_Case1 of string * type2
| T1_Case2 of type3
and type2 = type3 list
and type3_ =
| T3_Case1 of type1
| T3_Case2 of int
and type3 = Annotation.t * type3_
end
module M = struct
include M_F(struct type t = unit end)
end
我想我需要这样的东西(因为我不能在类型声明中使用函子应用程序,所以不起作用):
如果从functor切换到参数化类型,则可以尝试工作,如下所示:
module type AnnotatorType = sig
type 'a annotated
end
module Annotated_M(Annotator: AnnotatorType) = struct
type type1 =
| T1_Case1 of string * type2
| T1_Case2 of type3
and type2 = type3 list
and type3_ =
| T3_Case1 of type1
| T3_Case2 of int
and type3 = type3_ Annotator.annotated
end
module M = struct
include Annotated_M(struct
type 'a annotated = 'a
end)
end
module M2 = struct
include Annotated_M(struct
type 'a annotated = extra_data * 'a
end)
end
这听起来像是问题的一个例子,尽管问题
Y
有技术上的解决办法,但问题X
仍然会存在。稍后让我详细介绍一下,但现在我要提出几个技术解决方案
module type Variants = sig
type t1
type t2
...
end
module Define(V : Variants) = struct
type t = V of t1 | V of t2 ...
end
type ('a,'b,..) t = A of 'a | B of 'b
X
问题做一点详细说明。我的猜测是,您试图表示语言的一些转换(即,一些中间表示、DSL等)。你有一对表示,它们彼此非常同构,但是它们定义了不同的类型,你感觉到的问题是这两种类型的定义中涉及的代码重复。代码重复是遗漏抽象的常见指标。OCaml中的类型定义不引入抽象,而是定义类型的表示。抽象是由模块类型引入的,并由使用特定类型表示的模块实现。因此,您真正需要解决X
问题的是一个适当的抽象。在我们的例子中,依赖标记嵌入迫使我们披露我们的表示,并使其具体化而不是抽象化。这有时很方便,但相当脆弱,很快就会导致代码重复。一个可能的解决方案是,它允许我们定义可扩展的抽象,而不必拘泥于特定的表示
type ('a,'b,..) t = A of 'a | B of 'b