如何按类型构造函数比较相等值?

沃伦·西摩

背景

我是Reason的新手,对于比较带有参数的变量有多么容易,我感到很惊讶:

type t = Header | Int(int) | String(string) | Ints(list(int)) | Strings(list(string)) | Footer;

比较不同的变体很好并且可以预测:

/* not equal */
Header == Footer
Int(1) == Footer
Int(1) == Int(2)

/* equal */
Int(1) == Int(1)

这甚至适用于复杂类型:

/* equal */
Strings(["Hello", "World"]) == Strings(["Hello", "World"])

/* not equal */
Strings(["Hello", "World"]) == Strings(["a", "b"])

是否可以通过我无法找到的现有内置运算符/函数或某些其他语言构造来仅比较类型构造器?

let a = String("a");
let b = String("b");

/* not equal */
a == b

/* for sake of argument, I want to consider all `String(_)` equal, but how? */
格伦斯

可以通过检查值的内部表示形式来实现,但是我不建议这样做,因为它相当脆弱,而且我不确定跨这些内部版本的编译器版本和各种后端会做出什么保证。相反,我建议您要么编写手工构建的函数,要么使用一些ppx生成与您手工编写的代码相同的代码。

但这没什么好玩的,所以所有这些,应该使用很少记录的Obj模块来完成您想要的事情

let equal_tag = (a: 'a, b: 'a) => {
  let a = Obj.repr(a);
  let b = Obj.repr(b);

  switch (Obj.is_block(a), Obj.is_block(b)) {
  | (true, true) => Obj.tag(a) == Obj.tag(b)
  | (false, false) => a == b
  | _ => false
  };
};

哪里

equal_tag(Header, Footer) == false;
equal_tag(Header, Int(1)) == false;
equal_tag(String("a"), String("b")) == true;
equal_tag(Int(0), Int(0)) == true;

要了解此功能的工作原理,您需要了解OCaml如何在内部表示值。在OCaml手册的C与OCaml的接口一章中有关OCaml数据类型的表示的部分中进行了描述(例如,尽管我相信它确实适用于各种JavaScript后端,但在这里我们已经看到一些迹象表明这可能并不适用于各种JavaScript后端)。至少现在是这样。我已经用BuckleScript / rescript测试过了,而js_of_ocaml倾向于更接近内部。)

具体而言,本节对变量的表示方式进行了以下说明:

type t =
  | A             (* First constant constructor -> integer "Val_int(0)" *)
  | B of string   (* First non-constant constructor -> block with tag 0 *)
  | C             (* Second constant constructor -> integer "Val_int(1)" *)
  | D of bool     (* Second non-constant constructor -> block with tag 1 *)
  | E of t * t    (* Third non-constant constructor -> block with tag 2 *)

也就是说,没有有效负载的构造函数直接表示为整数,而具有有效负载的构造函数则表示为带有标签的“块”。还要注意,块标记和非块标记是独立的,因此我们不能首先从比较的值中提取一些“通用”标记值。相反,我们必须检查它们是否都是块,然后比较它们的标签。

最后,请注意,尽管此函数将接受任何类型的值,但在编写时仅考虑了变体。比较其他类型的值可能会产生意外的结果。这是不使用它的另一个很好的理由。

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

按相等值过滤数组

当参数是整数表示为字符串时,比较函数中的两个相等值返回 False

列中的相等值

如何选择列中具有相等值的行

如何合并具有相等值的单元格

如何在J中将相等值分组?

如何使数组中的相等值写入括号内?

如何使数组中的相等值写入括号内?

如何使一个函数接受两个带有返回相等值的字符串的集合?(JavaScript)

使用*和&比较相等值之间有什么区别?

Pandas Groupby比较Excel中带有子行的2列中的计数相等值

比较组并获得所有组的相等值(pandas groupby)

如何合并列表中具有相等值的字典并串联不相等的值?

列表Java中的相等值

防止 jQuery UI 滑块相等值

如何按Excel或GSheet中第二列的值对第一列中具有相等值的列表进行排序?

在窗口函数中对具有相等值的行进行计数

如何在熊猫的NaN值之间重新分配相等值?

如何编写 Rails SQL 查询以查找所有子项具有相等值的对象

如何删除在Matlab的指定列中矩阵A与矩阵B具有相等值的那些行?

如何使用 ngrx 和 typescript 连接具有相等值的属性上的列表项

如何选择列中具有相等值的线并保持此特性

mySQL:如何过滤其他表中没有相等值的列?

逐行比较两个不同长度的数据帧,并为每行添加具有相等值的列

比较两个数组以在Google应用程序脚本中找到相等值的最快方法

将向量拆分为相等值的连续游程

查询优化以匹配具有相等值的节点

枚举PySpark中连续相等值的组

Kotlin的sortedBy是否保持相等值的顺序?