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

时间:2011-06-29 14:28:46

标签: 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 _ -> true);;

当类型

上有许多构造函数时会变得非常混乱

3 个答案:

答案 0 :(得分:8)

你可以重写上面的内容,有点简单:

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

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

答案 1 :(得分:6)

这可以通过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_constructors;您将获得truefalse返回值,但不一定是有意义的值。

答案 2 :(得分:4)

另一种可以正常工作的方法是创建与标记对应的另一种类型,并使用该类型。

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