用于表示具有多个参数的函数应用程序的GADT(AST)

时间:2015-04-04 17:32:10

标签: ocaml abstract-syntax-tree gadt

我在OCaml手册中看到这个例子使用GADT作为带功能应用的AST:

type _ term =
  | Int : int -> int term
  | Add : (int -> int -> int) term
  | App : ('b -> 'a) term * 'b term -> 'a term

let rec eval : type a. a term -> a = function
  | Int n    -> n
  | Add      -> (fun x y -> x+y)
  | App(f,x) -> (eval f) (eval x)

这是表示支持部分申请的语言的功能应用程序的正确方法吗?

有没有办法让GADT支持具有任意数量参数的函数应用程序?

最后,GADT是表示类型化AST的好方法吗?还有其他选择吗?

1 个答案:

答案 0 :(得分:2)

嗯,部分评估已在这里工作:

# eval (App(App(Add, Int 3),Int 4)) ;;
- : int = 7   

# eval (App(Add, Int 3)) ;;
- : int -> int = <fun>   

# eval (App(Add, Int 3)) 4 ;;
- : int = 7   

你在这个小城市中没有的是抽象(lambdas),但绝对可以添加它。

如果您对该主题感兴趣,则会有大量(学术)文献。 This论文提供了支持部分评估的各种编码。

还有非Gadt解决方案,如this paper所示。

通常,GADT是表示评估者的一种非常有趣的方式。当你试图将AST转换为编译时,它们往往会有点短暂(但有ways)。

此外,您必须记住,您正在使用主机语言对您定义的语言的类型系统进行编码,这意味着您需要对所需类型功能进行编码。有时,这很棘手。

编辑:让GADT 支持部分评估的方法是使用不包含函数的特殊值类型和具有函数的“功能值”类型。以第一篇论文的最简单表示形式,我们可以这样修改它:

type _ v =
  | Int : int -> int v
  | String : string -> string v

and _ vf =
  | Base : 'a v -> ('a v) vf
  | Fun : ('a vf -> 'b vf) -> ('a -> 'b) vf

and _ t =
  | Val : 'a vf -> 'a t
  | Lam : ('a vf -> 'b t) -> ('a -> 'b) t
  | App : ('a -> 'b) t * 'a t -> 'b t

let get_val : type a . a v -> a = function
  | Int i -> i
  | String s -> s

let rec reduce : type a . a t -> a vf = function
  | Val x -> x
  | Lam f -> Fun (fun x -> reduce (f x))
  | App (f, x) -> let Fun f = reduce f in f (reduce x)

let eval t =
  let Base v = reduce t in get_val v

(* Perfectly defined expressions. *)
let f = Lam (fun x -> Lam (fun y -> Val x))
let t = App (f, Val (Base (Int 3)))
(* We can reduce t to a functional value. *)
let x = reduce t
(* But we can't eval it, it's a type error. *)
let y = eval t

(* HOF are authorized. *)
let app = Lam (fun f -> Lam (fun y -> App(Val f, Val y)))

根据您的需要,您可以根据需要更加复杂,重要的属性是'a v类型无法生成函数。