将GADT转换为幻影类型



我在OCAML中与GADT和幻影类型一起玩。我知道Gadt是描述某些类型的幻影类型的便利性 - 如果我错了,请务必纠正我。因此,我决定尝试使用GADT类型将程序转换为具有ADT和幻影类型的程序。

我从此博客文章中获取了一个GADT程序作为起点。这是一个小的bool/int表达评估器,这是它的要旨:

module GADT = struct
  type _ value =
    | Bool : bool -> bool value
    | Int : int -> int value
  type _ expr =
    | Value : 'a value -> 'a expr
    | If : bool expr * 'a expr * 'a expr -> 'a expr
    | Eq : 'a expr * 'a expr -> bool expr
    | Lt : int expr * int expr -> bool expr
  let rec eval : type a. a expr -> a = function
    | Value (Bool b) -> b
    | Value (Int i) -> i
    | If (b, l, r) -> if eval b then eval l else eval r
    | Eq (a, b) -> eval a = eval b
    | Lt (a,b) -> a < b
end

因此,我开始将其转换为ADT 幻影类型,如下所示:

module ADT = struct
  type 'a value =
    | Bool of bool
    | Int of int
  let _Bool b : bool value = Bool b
  let _Int  i :  int value = Int i
  type 'a expr =
    | Value of 'a value
    | If of bool expr * 'a expr * 'a expr
    | Eq of 'a expr * 'a expr
    | Lt of int expr * int expr
  let _Value v : 'a expr = Value v
  let _If (cond, cons, alt) : 'a expr = If (cond, cons, alt)
  let _Eq (left, right) : bool expr = Eq (left, right)
  let _Lt (left, right) : bool expr = Lt (left, right)
  let rec eval : type a. a expr -> a = function
    | Value (Bool b) -> b
    | Value (Int  i) -> i
    | If (cond, cons, alt) -> if eval cond then eval cons else eval alt
    | Eq (left, right) -> eval left = eval right
    | Lt (left, right) -> left < right
end

您无法控制ADT构造函数的类型变量,因此我创建了自己的_Bool_Int等。

但是,我的ADT模块不编译:

  let rec eval : type a. a expr -> a = function
    | Value (Bool b) -> b
                        ^
Error: This expression has type bool but an expression was expected of type a 

在这一点上,我认为我的想法是有缺陷的,您不能以这种方式将GADT转换为ADT。但是我想听听这个主题上更有经验的人。

如果没有GADT,您将无法做到这一点,因为Phantom类型不能作为编译器的证人,即表达式具有特定类型,因为使用Phantom类型,您实际上可以做以下操作:

let bool b : int value = Bool b;;
val bool : bool -> int value = <fun>

这就是为什么拥有幻影类型不够的原因,这就是为什么在OCAML中引入GADT的原因。

最新更新