OCaml等价类型

7
我正在使用OCaml构建两个库,它们包含相同的变量类型。除了它非常庞大,手动编写转换函数会很麻烦外,其细节并不太重要。(实际上,它是使用ocamlidl从C转换而来的bfd_architecture枚举)。
现在我正在编写一个程序,使用这两个库。特别地,我调用A.f,它返回A.variant_type的值,并且我需要在调用B.g时使用该值,B.g以B.variant_type的值作为输入。
有没有办法告诉OCaml,A.variant_type和B.variant_type实际上是相同的类型,因此将一个值从一个类型转换为另一个类型是可以的?这些库是独立的,所以它们不应该相互引用。现在我正在使用Obj.magic进行转换,但这只是一种hack方法。

为什么不能像ygrek建议的那样,让这两个库共享同一种变量类型,而不是生成两个具有相同结构的不同变量? - gasche
4
换句话说,将变体类型放到第三个模块中,并在其他模块中使用它。您可以open该模块以使命名更轻便。 - Jeffrey Scofield
3个回答

9

我认为,除非这些库有一些公共依赖项来定义这种类型(即在构建时从两个库引用的相同模块),否则没有干净的方法。


4

如果你真的希望变量类型在两个库中都出现,你也可以强制检查它们是否相等。在第二个库中,你可以这样写:

type t = OtherLib.t = | A | B | C | ...

这将使编译器验证OtherLib.t = A | B | C | ...,并使两个类型相等。我认为这并不能真正解决您的问题,因为您可能不想更改任何一个库。
当我想保留类型的不同版本(因为它们保存在我想要稍后读取的文件中)并且希望每个版本都显式构造函数时,我通常会这样做,同时尽可能保持与当前版本的等价性。

非常接近所需的,这真是令人沮丧。令人惊讶的是,你可以做到这一点,却不能做到类型t = Firstlib.t = Secondlib.t。 - Ed McMan

2

您不必使用Obj.magic,尽管您确实需要使用一些“魔法”,

external convertAB : A.t -> B.t = "%identity"
external convertBA : B.t -> A.t = "%identity"

只需进行转换即可。当然,我理解您的担忧;两种类型必须完全相同,否则您将处理运行时错误。如果可能且相关,将这些变量转换为多态变量将解决该问题。


1
使用多态变体是解决一般问题的好方法。在我的情况下,我正在使用ocamlidl生成变体类型,并且我没有看到强制它输出多态变体的可选项。 - Ed McMan
3
我确定你知道这个,但是使用 "%identity" 和使用 Obj.magic 是完全相同的(实际上是相同的)。如果有可能,你真的应该避免使用它们。 - Jeffrey Scofield
哦是这样。我刚才查看了源代码。好知道。 - nlucaroni
1
我认为Jeffrey在评论中提供的答案,使用第三方库,是值得探索的好选择。 - nlucaroni

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接