Creating GADT expression in OCaml

前端 未结 2 781
不思量自难忘°
不思量自难忘° 2020-12-10 06:22

There is my toy GADT expression:

type _ expr =
  | Num : int -> int expr
  | Add : int expr * int expr -> int expr
  | Sub : int expr * int expr ->          


        
相关标签:
2条回答
  • 2020-12-10 07:08

    As you've found, this approach doesn't type check. It also has a more fundamental problem: GADTs can be recursive, in which case it is flatly impossible to enumerate their cases.

    Instead you can reify types as a GADT and pass them around. Here's a cut-down example:

    type _ expr =
      | Num : int -> int expr
      | Add : int expr * int expr -> int expr
      | Lt  : int expr * int expr -> bool expr
      | And : bool expr * bool expr -> bool expr
    
    type _ ty =
      | TyInt : int ty
      | TyBool : bool ty
    
    let bin_op (type a) (type b) op (l : a expr) (r : a expr) (arg_ty : a ty) (ret_ty : b ty) : b expr =
      match op, arg_ty, ret_ty with
      | '+', TyInt, TyInt -> Add (l, r)
      | '<', TyInt, TyBool -> Lt (l, r)
      | '&', TyBool, TyBool -> And (l, r)
      | _, _, _ -> assert false
    

    At some point you are going to want to have a value that can be 'any expression'. Introducing an existential wrapper allows this. Cheesy example: generating random expression trees:

    type any_expr = Any : _ expr -> any_expr
    
    let rec random_int_expr () =
      if Random.bool () then Num (Random.int max_int)
      else Add (random_int_expr (), random_int_expr ())
    
    let rec random_bool_expr () =
      if Random.bool () then Lt (Num (Random.int max_int), Num (Random.int max_int))
      else And (random_bool_expr (), random_bool_expr ())
    
    let random_expr () =
      if Random.bool () then Any (random_int_expr ())
      else Any (random_bool_expr ())
    
    0 讨论(0)
  • 2020-12-10 07:22

    Your stated type for create_expr is char -> 'a expr -> 'a expr -> 'a expr. But the type for the '>' case would be char -> int expr -> int expr -> bool expr. So it seems there are problems with the basic plan.

    In essence you want the type of the result to depend on the value of the character. I'm not absolutely positive, but I suspect this isn't possible in OCaml. Seems like it would require a more powerful type system.

    0 讨论(0)
提交回复
热议问题