How to check whether two values are created with the same constructor?

霸气de小男生 提交于 2020-01-03 13:36:14

问题


let's say I have

type t = A of int | B of int

let xx = A(2);;
let yy = A(3);;

and I want to test if the constructors of xx and yy are equal, is there an easy way to do this ? Instead of having to

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

which gets quite messy when there many constructors on a type


回答1:


You can rewrite the above to, somewhat simpler:

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

but I'm not aware of a solution without enumerating all the constructors.




回答2:


This is possible, sort of, through the Obj module. Analyzing objects through the Obj functions, if done properly, won't crash your program; but you need to be careful if you want to get meaningful results.

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

When called on values of a variant type (not a polymorphic variant type), this function returns true if the two values both have the same zero-argument constructor or both have the same 1-or-more-argument constructor, and false otherwise. The type system won't prevent you from instanciating equal_constructors at other types; you'll get a true or false return value but not necessarily a meaningful one.




回答3:


Another way of doing this that can work well is to create another type that corresponds to the tags, and use that type.

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


来源:https://stackoverflow.com/questions/6522360/how-to-check-whether-two-values-are-created-with-the-same-constructor

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!