comparison src/ProgLang.v @ 414:73f8165a3c1d

Typesetting pass over ProgLang
author Adam Chlipala <adam@chlipala.net>
date Fri, 08 Jun 2012 15:54:36 -0400
parents 05efde66559d
children 92f386c33e94
comparison
equal deleted inserted replaced
413:6f0f80ffd5b6 414:73f8165a3c1d
143 termDenote (ident e) s = termDenote e s. 143 termDenote (ident e) s = termDenote e s.
144 induction e; t. 144 induction e; t.
145 Qed. 145 Qed.
146 146
147 (** A slightly more ambitious transformation belongs to the family of _constant folding_ optimizations we have used as examples in other chapters. *) 147 (** A slightly more ambitious transformation belongs to the family of _constant folding_ optimizations we have used as examples in other chapters. *)
148
149 Axiom admit : forall T, T.
150 148
151 Fixpoint cfold G t (e : term G t) : term G t := 149 Fixpoint cfold G t (e : term G t) : term G t :=
152 match e with 150 match e with
153 | Plus G e1 e2 => 151 | Plus G e1 e2 =>
154 let e1' := cfold e1 in 152 let e1' := cfold e1 in
178 176
179 Theorem cfoldSound : forall G t (e : term G t) s, 177 Theorem cfoldSound : forall G t (e : term G t) s,
180 termDenote (cfold e) s = termDenote e s. 178 termDenote (cfold e) s = termDenote e s.
181 induction e; t; 179 induction e; t;
182 repeat (match goal with 180 repeat (match goal with
183 | [ |- context[match ?E with 181 | [ |- context[match ?E with Var _ _ _ => _ | _ => _ end] ] =>
184 | Var _ _ _ => _ | Const _ _ => _ | Plus _ _ _ => _ 182 dep_destruct E
185 | Abs _ _ _ _ => _ | App _ _ _ _ _ => _
186 | Let _ _ _ _ _ => _
187 end] ] => dep_destruct E
188 end; t). 183 end; t).
189 Qed. 184 Qed.
190 185
191 (** The transformations we have tried so far have been straightforward because they do not have interesting effects on the variable binding structure of terms. The dependent de Bruijn representation is called %\index{first-order syntax}%_first-order_ because it encodes variable identity explicitly; all such representations incur bookkeeping overheads in transformations that rearrange binding structure. 186 (** The transformations we have tried so far have been straightforward because they do not have interesting effects on the variable binding structure of terms. The dependent de Bruijn representation is called%\index{first-order syntax}% _first-order_ because it encodes variable identity explicitly; all such representations incur bookkeeping overheads in transformations that rearrange binding structure.
192 187
193 As an example of a tricky transformation, consider one that removes all uses of %``%#"#[let x = e1 in e2]#"#%''% by substituting [e1] for [x] in [e2]. We will implement the translation by pairing the %``%#"#compile-time#"#%''% typing environment with a %``%#"#run-time#"#%''% value environment or _substitution_, mapping each variable to a value to be substituted for it. Such a substitute term may be placed within a program in a position with a larger typing environment than applied at the point where the substitute term was chosen. To support such context transplantation, we need _lifting_, a standard de Bruijn indices operation. With dependent typing, lifting corresponds to weakening for typing judgments. 188 As an example of a tricky transformation, consider one that removes all uses of %``%#"#[let x = e1 in e2]#"#%''% by substituting [e1] for [x] in [e2]. We will implement the translation by pairing the %``%#"#compile-time#"#%''% typing environment with a %``%#"#run-time#"#%''% value environment or _substitution_, mapping each variable to a value to be substituted for it. Such a substitute term may be placed within a program in a position with a larger typing environment than applied at the point where the substitute term was chosen. To support such context transplantation, we need _lifting_, a standard de Bruijn indices operation. With dependent typing, lifting corresponds to weakening for typing judgments.
194 189
195 The fundamental goal of lifting is to add a new variable to a typing context, maintaining the validity of a term in the expanded context. To express the operation of adding a type to a context, we use a helper function [insertAt]. *) 190 The fundamental goal of lifting is to add a new variable to a typing context, maintaining the validity of a term in the expanded context. To express the operation of adding a type to a context, we use a helper function [insertAt]. *)
196 191
316 (** The [Let] removal optimization is a good case study of a simple transformation that may turn out to be much more work than expected, based on representation choices. In the second part of this chapter, we consider an alternate choice that produces a more pleasant experience. *) 311 (** The [Let] removal optimization is a good case study of a simple transformation that may turn out to be much more work than expected, based on representation choices. In the second part of this chapter, we consider an alternate choice that produces a more pleasant experience. *)
317 312
318 313
319 (** * Parametric Higher-Order Abstract Syntax *) 314 (** * Parametric Higher-Order Abstract Syntax *)
320 315
321 (** In contrast to first-order encodings, %\index{higher-order syntax}%_higher-order_ encodings avoid explicit modeling of variable identity. Instead, the binding constructs of an %\index{object language}%_object language_ (the language being formalized) can be represented using the binding constructs of the %\index{meta language}%_meta language_ (the language in which the formalization is done). The best known higher-order encoding is called %\index{higher-order abstract syntax}\index{HOAS}%_higher-order abstract syntax (HOAS)_ %\cite{HOAS}%, and we can start by attempting to apply it directly in Coq. *) 316 (** In contrast to first-order encodings,%\index{higher-order syntax}% _higher-order_ encodings avoid explicit modeling of variable identity. Instead, the binding constructs of an%\index{object language}% _object language_ (the language being formalized) can be represented using the binding constructs of the%\index{meta language}% _meta language_ (the language in which the formalization is done). The best known higher-order encoding is called%\index{higher-order abstract syntax}\index{HOAS}% _higher-order abstract syntax_ (HOAS) %\cite{HOAS}%, and we can start by attempting to apply it directly in Coq. *)
322 317
323 Module HigherOrder. 318 Module HigherOrder.
324 319
325 (** With HOAS, each object language binding construct is represented with a _function_ of the meta language. Here is what we get if we apply that idea within an inductive definition of term syntax. *) 320 (** With HOAS, each object language binding construct is represented with a _function_ of the meta language. Here is what we get if we apply that idea within an inductive definition of term syntax. *)
326 321
335 | Let : forall t1 t2, term t1 -> (term t1 -> term t2) -> term t2. 330 | Let : forall t1 t2, term t1 -> (term t1 -> term t2) -> term t2.
336 ]] 331 ]]
337 332
338 However, Coq rejects this definition for failing to meet the %\index{strict positivity restriction}%strict positivity restriction. For instance, the constructor [Abs] takes an argument that is a function over the same type family [term] that we are defining. Inductive definitions of this kind can be used to write non-terminating Gallina programs, which breaks the consistency of Coq's logic. 333 However, Coq rejects this definition for failing to meet the %\index{strict positivity restriction}%strict positivity restriction. For instance, the constructor [Abs] takes an argument that is a function over the same type family [term] that we are defining. Inductive definitions of this kind can be used to write non-terminating Gallina programs, which breaks the consistency of Coq's logic.
339 334
340 An alternate higher-order encoding is %\index{parametric higher-order abstract syntax}\index{PHOAS}%_parametric HOAS_, as introduced by Washburn and Weirich%~\cite{BGB}% for Haskell and tweaked by me%~\cite{PhoasICFP08}% for use in Coq. Here the idea is to parametrize the syntax type by a type family standing for a _representation of variables_. *) 335 An alternate higher-order encoding is%\index{parametric higher-order abstract syntax}\index{PHOAS}% _parametric HOAS_, as introduced by Washburn and Weirich%~\cite{BGB}% for Haskell and tweaked by me%~\cite{PhoasICFP08}% for use in Coq. Here the idea is to parametrize the syntax type by a type family standing for a _representation of variables_. *)
341 336
342 Section var. 337 Section var.
343 Variable var : type -> Type. 338 Variable var : type -> Type.
344 339
345 Inductive term : type -> Type := 340 Inductive term : type -> Type :=
558 553
559 Lemma cfoldSound : forall t (e : term typeDenote t), 554 Lemma cfoldSound : forall t (e : term typeDenote t),
560 termDenote (cfold e) = termDenote e. 555 termDenote (cfold e) = termDenote e.
561 induction e; t; 556 induction e; t;
562 repeat (match goal with 557 repeat (match goal with
563 | [ |- context[match ?E with 558 | [ |- context[match ?E with Var _ _ => _ | _ => _ end] ] =>
564 | Var _ _ => _ | Const _ => _ | Plus _ _ => _ 559 dep_destruct E
565 | Abs _ _ _ => _ | App _ _ _ _ => _
566 | Let _ _ _ _ => _
567 end] ] => dep_destruct E
568 end; t). 560 end; t).
569 Qed. 561 Qed.
570 562
571 Theorem CfoldSound : forall t (E : Term t), 563 Theorem CfoldSound : forall t (E : Term t),
572 TermDenote (Cfold E) = TermDenote E. 564 TermDenote (Cfold E) = TermDenote E.
702 Have we really avoided first-order reasoning about the output terms of translations? The answer depends on some subtle issues, which deserve a subsection of their own. *) 694 Have we really avoided first-order reasoning about the output terms of translations? The answer depends on some subtle issues, which deserve a subsection of their own. *)
703 695
704 696
705 (** ** Establishing Term Well-Formedness *) 697 (** ** Establishing Term Well-Formedness *)
706 698
707 (** Can there be values of type [Term t] that are not well-formed according to [Wf]? We expect that Gallina satisfies key %\index{parametricity}%_parametricity_ %\cite{parametricity}% properties, which indicate how polymorphic types may only be inhabited by specific values. We omit details of parametricity theorems here, but [forall t (E : Term t), Wf E] follows the flavor of such theorems. One option would be to assert that fact as an axiom, %``%#"#proving#"#%''% that any output of any of our translations is well-formed. We could even prove the soundness of the theorem on paper meta-theoretically, say by considering some particular model of CIC. 699 (** Can there be values of type [Term t] that are not well-formed according to [Wf]? We expect that Gallina satisfies key%\index{parametricity}% _parametricity_ %\cite{parametricity}% properties, which indicate how polymorphic types may only be inhabited by specific values. We omit details of parametricity theorems here, but [forall t (E : Term t), Wf E] follows the flavor of such theorems. One option would be to assert that fact as an axiom, %``%#"#proving#"#%''% that any output of any of our translations is well-formed. We could even prove the soundness of the theorem on paper meta-theoretically, say by considering some particular model of CIC.
708 700
709 To be more cautious, we could prove [Wf] for every term that interests us, threading such proofs through all transformations. Here is an example exercise of that kind, for [Unlet]. 701 To be more cautious, we could prove [Wf] for every term that interests us, threading such proofs through all transformations. Here is an example exercise of that kind, for [Unlet].
710 702
711 First, we prove that [wf] is _monotone_, in that a given instance continues to hold as we add new variable pairs to the variable isomorphism. *) 703 First, we prove that [wf] is _monotone_, in that a given instance continues to hold as we add new variable pairs to the variable isomorphism. *)
712 704