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

发布于 2024-11-17 14:57:48 字数 356 浏览 1 评论 0原文

假设我有

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);;

当类型上有很多构造函数时,

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

夜空下最亮的亮点 2024-11-24 14:57:48

您可以将上面的内容重写为更简单一些:

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

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

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.

浅忆流年 2024-11-24 14:57:48

这在某种程度上可以通过 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-or-more-,则此函数返回 true参数构造函数,否则为 false。类型系统不会阻止您在其他类型上实例化equal_constructors;您将得到一个 truefalse 返回值,但不一定是有意义的。

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.

望喜 2024-11-24 14:57:48

另一种有效的方法是创建与标签相对应的另一种类型,并使用该类型。

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

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
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文