Ну, частичная Eval уже работает здесь:
# 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
То, что вы не в этой маленькой gadt это абстракция (лямбды), но это, безусловно, можно добавить его.
Если вас интересует эта тема, существует обширная (академическая) литература. This В документе представлена различная кодировка, которая поддерживает частичную оценку.
Существуют также решения без гадта, как показано в this paper.
В целом, GADT - очень интересный способ представить оценщиков. Они, как правило, немного сокращаются, когда вы пытаетесь преобразовать AST для компиляций (но есть ways).
Кроме того, вы должны иметь в виду, что вы кодируете систему типов языка, который вы определяете на своем языке хоста, а это значит, что вам нужна кодировка требуемой функции типа. Иногда это сложно.
Редактировать: способ иметь GADT не, поддерживающий частичный eval, должен иметь специальный тип значения, не содержащий функций, и тип «функционального значения» с функциями. Принимая простейшее представление первой статьи, мы можем изменить его таким образом:
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)))
Вы можете сделать это arbitrarly более сложным, следуя ваши потребности, важное свойство является то, что 'a v
типа не может производить функции.
Я знаю, что частичное приложение поддерживается этим GADT, но я хочу сделать GADT **, а не ** поддерживать его (для C-подобного языка), поддерживая при этом несколько аргументов. Я мог бы использовать текущий GADT для этого (используя частичное приложение), но проблема, которую я вижу при таком подходе, заключается в том, что я могу создать AST, который является недопустимым. Поскольку я хочу сделать компиляцию, я рассмотрю другие решения, но мне все же интересно посмотреть, что является решением проблемы в моем вопросе. – antoyo
Вы также хотите запретить функции высокого порядка? – Drup
Нет, но я не знаю, как сделать GADT для представления этого. – antoyo