Ocaml 如何检查是否使用同一构造函数创建了两个值?

Ocaml 如何检查是否使用同一构造函数创建了两个值?,ocaml,Ocaml,假设我有 type t = A of int | B of int let xx = A(2);; let yy = A(3);; 我想测试xx和yy的构造函数是否相等, 有没有一个简单的方法可以做到这一点?而不是必须 match xx with A _ -> (match yy with A _ -> true | B _ -> false) | B _ -> (match yy with A _ -> false | B _ -> tru

假设我有

type t = A of int | B of int

let xx = A(2);;
let yy = A(3);;
我想测试xx和yy的构造函数是否相等, 有没有一个简单的方法可以做到这一点?而不是必须

match xx with
  A _ ->
  (match yy with A _ -> true | B _ -> false)
| B _ -> 
  (match yy with A _ -> false | B _ -> true);;

当一个类型上有许多构造函数时,这会变得非常混乱。您可以将上面的内容重写为更简单的内容:

match xx, yy with
| A _, A _
| B _, B _ -> true
| (A _ | B _), _ -> false

但是我不知道没有枚举所有构造函数的解决方案。

这在某种程度上是可能的,通过
Obj
模块。通过
Obj
函数分析对象,如果操作正确,不会使程序崩溃;但是如果你想得到有意义的结果,你需要小心

let equal_constructors (x : 'a) (y : 'a) =
  let r = Obj.repr x and s = Obj.repr y in
  if Obj.is_int r && Obj.is_int s then (Obj.obj r : int) = (Obj.obj s : int) else
  if Obj.is_block r && Obj.is_block s then Obj.tag r = Obj.tag s else
  false

在变量类型(非多态变量类型)的值上调用时,如果两个值都具有相同的零参数构造函数或具有相同的1个或多个参数构造函数,则此函数返回
true
,否则返回
false
。类型系统不会阻止您在其他类型上实例化
equal_构造函数
;您将得到一个
true
false
返回值,但不一定是一个有意义的返回值。

另一种方法是创建另一个与标记对应的类型,并使用该类型

type t = A of int | B of int
module Tag = struct type t = A | B end

let to_tag = function A _ -> Tag.A | B _ -> Tag.B
let tags_are_equal x y =
    to_tag x = to_tag y

这是正确的,但通常明智的做法是避免使用
,\u
,最好使用
(A 124; B),\u
。这样,如果构造函数更改,编译器可以帮助您查找错误。关于这一点有一个讨论,可以通过比较值的标记来完成(使用适当的类型注释非常安全):@niucaroni:的确,这是一个很好的观点。我冒昧地把它合并到了答案中。这是一个有点丑陋的低级黑客,并且非常依赖于编译器实现的细节。下面的解决方案更可取。@yzzlr C接口的规范保证了我的代码所依赖的表示属性。所以,是的,这是一个丑陋的低级黑客,但它所依赖的是(仅)实现的记录行为的一部分。