繁体   English   中英

OCaml - GADT - 布尔表达式

[英]OCaml - GADT - Boolean expression

我想知道是否有某种方法可以做到这一点:

type binary_operator = And | Or;;

type canonical;;
type not_canonical;;

type 'canonical boolean_expression =
  | Var : int -> not_canonical boolean_expression
  | Not : 'canonical boolean_expression -> 'canonical boolean_expression
  | BinOp : canonical boolean_expression * binary_operator * canonical boolean_expression -> canonical boolean_expression
  | BinOp : _ boolean_expression * binary_operator * _ boolean_expression -> not_canonical boolean_expression
;;

这里的问题是我无法定义BinOp两次,而我想依赖于参数的类型......

PS:“规范”意味着“表达式中包含的n个变量由0到(n-1)的整数表示”。 这是一个不变的,我需要强制我的一些功能。

您必须为类型构造器指定不同的名称,因为有些情况下gadt的行为与adt相似。

我们假设你想要定义你的类型如下:

type 'canonical boolean_expression =
  | Bool : bool -> canonical boolean_expression (* here I assume that you wanted to have that case too *)
  | Var : int -> not_canonical boolean_expression
  | Not : 'canonical boolean_expression -> 'canonical boolean_expression
  | BinOpC : canonical boolean_expression * binary_operator * canonical boolean_expression -> canonical boolean_expression
  | BinOpNC : _ boolean_expression * binary_operator * _ boolean_expression -> not_canonical boolean_expression
 ;;

现在考虑稍微修改一下这种类型:

type 'canonical boolean_expression =
  | Bool : bool -> canonical boolean_expression
  | Var : int -> not_canonical boolean_expression
  | Not : 'canonical boolean_expression -> 'canonical boolean_expression
  | BinOpC : canonical boolean_expression * binary_operator * canonical boolean_expression -> canonical boolean_expression
  | BinOpNC : 'a boolean_expression * binary_operator * 'a boolean_expression -> 'a boolean_expression
;;

现在,您最终可以使用最后两个构造函数中的任何一个进行canonical boolean_expression的二元运算。 显然,通过任意选择结果值的类型而获得的自由有其结果:您可以创建具有重叠“类型案例”的小工具。 执行此操作时,任何采用这些值之一的函数都必须测试这两种情况。 因此构造函数的名称不能相同,因为类型可能不足以知道我们正在处理哪些值。

例如,下面的功能:

 let rec compute = function 
    | Bool b -> b   
    | BinOpC (a,And,b) -> compute a && compute b
    | BinOpC (a,Or,b) -> compute a || compute b
 ;;

鉴于你的定义,应该没有问题地检查和处理规范表达。 通过我的修改,编译器会正确地抱怨BinOpNC也可以包含canonical表达式。

这似乎是一个愚蠢的例子(实际上是)暴露gadt的这个方面,因为我修改的布尔表达式的定义明显是不正确的(从语义上讲),但编译器并不关心类型的实用意义。

从本质上讲,gadt仍然是adt,因为你仍然可以找到一些情况,你必须依靠构造函数来选择正确的行动方案。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM