-
Notifications
You must be signed in to change notification settings - Fork 52
/
example_record_to_sigma.v
67 lines (56 loc) · 2.59 KB
/
example_record_to_sigma.v
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
From elpi Require Import elpi.
(* Define a command to turn records into nested sigma types, suggested
by M. Maggesi for the UniMath library *)
Elpi Command UM.expand.
Elpi Accumulate lp:{{
% From a record declaration to an iterated sigma type
pred wrap-fields-ty i:record-decl, o:term.
wrap-fields-ty (field _ _ Ty _\ end-record) Ty.
wrap-fields-ty (field _ Proj Ty Fields) {{ sigT lp:F }} :-
coq.string->name Proj Name,
F = fun Name Ty Bo,
pi x\ decl x Name Ty ==> wrap-fields-ty (Fields x) (Bo x).
% From a record declaration to a function building the iterated pairs
% [wrap-fields-bo Rec Acc SigmaTypeDef SigmaTypeName Builder BuilderType]
% Builder = fun arg1 .. argn => existT arg1 (existT arg2 (.. argn) ..)
% Acc gathers arg1 .. argn while building the fun
% SigmaTypeDef is used to fill in the implicit arguments of existT
% SigmaTypeName is used for BuilderType = forall arg1 .. argn, SigmaTypeName
pred wrap-fields-bo i:record-decl, i:list term, i:term, i:term, o:term, o:term.
wrap-fields-bo end-record Acc SigTy Sig T Sig :-
std.rev Acc Args,
wrap-fields-bo.aux Args SigTy T.
wrap-fields-bo (field _ Proj Ty Fields) Acc SigTy Sig (fun Name Ty Bo) (prod Name Ty Tgt) :-
coq.string->name Proj Name,
pi x\ decl x Name Ty ==> wrap-fields-bo (Fields x) [x|Acc] SigTy Sig (Bo x) (Tgt x).
wrap-fields-bo.aux [Last] _ Last.
wrap-fields-bo.aux [X|XS] {{ sigT lp:F }} {{ existT lp:F lp:X lp:Rest }} :-
F = fun _ _ G,
wrap-fields-bo.aux XS (G X) Rest.
% We declare the type and its constructor.
% Missing features:
% - parameters are not supported
% - projections are not synthesized
main [indt-decl (record Name _Sort Kname Fields)] :-
wrap-fields-ty Fields T,
std.assert-ok! (coq.typecheck T Ty) "oops, wrap-fields-ty is bugged",
coq.env.add-const Name T Ty _ C,
wrap-fields-bo Fields [] T (global (const C)) K KTy,
std.assert-ok! (coq.typecheck K KTy) "oops, wrap-fields-bo is bugged",
coq.env.add-const Kname K KTy _ _.
}}.
Elpi Export UM.expand.
(* From now on UM.expand is a regular command taking as the only argument
a record declaration. *)
UM.expand Record foo := mk_foo {
f1 : Type;
f2 : f1 -> Type;
f3 : forall t : f1, f2 t -> bool
}.
Print foo.
(* foo = {f1 : Type & {f2 : f1 -> Type & forall t : f1, f2 t -> bool}} : Type *)
Print mk_foo.
(* mk_foo = fun (f1 : Type) (f2 : f1 -> Type) (f3 : forall t : f1, f2 t -> bool) =>
existT (fun f4 : Type => {f5 : f4 -> Type & forall t : f4, f5 t -> bool}) f1
(existT (fun f4 : f1 -> Type => forall t : f1, f4 t -> bool) f2 f3)
: forall (f1 : Type) (f2 : f1 -> Type), (forall t : f1, f2 t -> bool) -> foo *)