(** * Types: Type Systems *) (** New topic: _type systems_ - This chapter: a toy type system - typing relation - _progress_ and _preservation_ theorems - Next chapter: _simply typed lambda-calculus_ *) Set Warnings "-notation-overridden,-parsing". From Coq Require Import Arith.Arith. From PLF Require Import Maps. From PLF Require Import Imp. From PLF Require Import Smallstep. Hint Constructors multi : core. (* ################################################################# *) (** * Typed Arithmetic Expressions *) (** - A simple toy language where expressions may fail with dynamic type errors - numbers (and arithmetic) - booleans (and conditionals) - Terms like [5 + true] and [if 42 then 0 else 1] are _stuck_. *) (* ================================================================= *) (** ** Syntax *) (** Here is the syntax, informally: t ::= tru | fls | test t then t else t | zro | scc t | prd t | iszro t And here it is formally: *) Inductive tm : Type := | tru : tm | fls : tm | test : tm -> tm -> tm -> tm | zro : tm | scc : tm -> tm | prd : tm -> tm | iszro : tm -> tm. (** _Values_ are [tru], [fls], and numeric values... *) Inductive bvalue : tm -> Prop := | bv_tru : bvalue tru | bv_fls : bvalue fls. Inductive nvalue : tm -> Prop := | nv_zro : nvalue zro | nv_scc : forall t, nvalue t -> nvalue (scc t). Definition value (t : tm) := bvalue t \/ nvalue t. Hint Constructors bvalue nvalue : core. Hint Unfold value : core. (* ================================================================= *) (** ** Operational Semantics *) (** ------------------------------- (ST_TestTru) test tru then t1 else t2 --> t1 ------------------------------- (ST_TestFls) test fls then t1 else t2 --> t2 t1 --> t1' ---------------------------------------------------- (ST_Test) test t1 then t2 else t3 --> test t1' then t2 else t3 t1 --> t1' ------------------ (ST_Scc) scc t1 --> scc t1' --------------- (ST_PrdZro) prd zro --> zro numeric value v ------------------- (ST_PrdScc) prd (scc v) --> v t1 --> t1' ------------------ (ST_Prd) prd t1 --> prd t1' ----------------- (ST_IszroZro) iszro zro --> tru numeric value v --------------------- (ST_IszroScc) iszro (scc v) --> fls t1 --> t1' ---------------------- (ST_Iszro) iszro t1 --> iszro t1' *) (** ... and then formally: *) Reserved Notation "t '-->' t'" (at level 40). Inductive step : tm -> tm -> Prop := | ST_TestTru : forall t1 t2, (test tru t1 t2) --> t1 | ST_TestFls : forall t1 t2, (test fls t1 t2) --> t2 | ST_Test : forall t1 t1' t2 t3, t1 --> t1' -> (test t1 t2 t3) --> (test t1' t2 t3) | ST_Scc : forall t1 t1', t1 --> t1' -> (scc t1) --> (scc t1') | ST_PrdZro : (prd zro) --> zro | ST_PrdScc : forall v, nvalue v -> (prd (scc v)) --> v | ST_Prd : forall t1 t1', t1 --> t1' -> (prd t1) --> (prd t1') | ST_IszroZro : (iszro zro) --> tru | ST_IszroScc : forall v, nvalue v -> (iszro (scc v)) --> fls | ST_Iszro : forall t1 t1', t1 --> t1' -> (iszro t1) --> (iszro t1') where "t '-->' t'" := (step t t'). Hint Constructors step : core. (** Notice that the [step] relation doesn't care about whether the expression being stepped makes global sense -- it just checks that the operation in the _next_ reduction step is being applied to the right kinds of operands. For example, the term [scc tru] cannot take a step, but the almost as obviously nonsensical term scc (test tru then tru else tru) can take a step (once, before becoming stuck). *) (* ================================================================= *) (** ** Normal Forms and Values *) (** The first interesting thing to notice about this [step] relation is that the strong progress theorem from the [Smallstep] chapter fails here. That is, there are terms that are normal forms (they can't take a step) but not values (because we have not included them in our definition of possible "results of reduction"). Such terms are _stuck_. *) Notation step_normal_form := (normal_form step). Definition stuck (t : tm) : Prop := step_normal_form t /\ ~ value t. Hint Unfold stuck : core. (** However, although values and normal forms are _not_ the same in this language, the set of values is a subset of the set of normal forms. This is important because it shows we did not accidentally define things so that some value could still take a step. *) Lemma value_is_nf : forall t, value t -> step_normal_form t. Proof. (* FILL IN HERE *) Admitted. (* QUIZ Is the following term stuck? iszro (test tru (scc zro) zro) (1) Yes (2) No *) (* QUIZ What about this one? test (scc zro) tru fls (1) Yes (2) No *) (* QUIZ What about this one? scc (scc zro) (1) Yes (2) No *) (* ================================================================= *) (** ** Typing *) (** _Types_ describe the possible shapes of values: *) Inductive ty : Type := | Bool : ty | Nat : ty. (* ================================================================= *) (** ** Typing Relations *) (** The _typing relation_ [|- t \in T] relates terms to the types of their results: --------------- (T_Tru) |- tru \in Bool --------------- (T_Fls) |- fls \in Bool |- t1 \in Bool |- t2 \in T |- t3 \in T -------------------------------------------- (T_Test) |- test t1 then t2 else t3 \in T -------------- (T_Zro) |- zro \in Nat |- t1 \in Nat ----------------- (T_Scc) |- scc t1 \in Nat |- t1 \in Nat ----------------- (T_Prd) |- prd t1 \in Nat |- t1 \in Nat -------------------- (T_IsZro) |- iszro t1 \in Bool *) Reserved Notation "'|-' t '\in' T" (at level 40). Inductive has_type : tm -> ty -> Prop := | T_Tru : |- tru \in Bool | T_Fls : |- fls \in Bool | T_Test : forall t1 t2 t3 T, |- t1 \in Bool -> |- t2 \in T -> |- t3 \in T -> |- test t1 t2 t3 \in T | T_Zro : |- zro \in Nat | T_Scc : forall t1, |- t1 \in Nat -> |- scc t1 \in Nat | T_Prd : forall t1, |- t1 \in Nat -> |- prd t1 \in Nat | T_Iszro : forall t1, |- t1 \in Nat -> |- iszro t1 \in Bool where "'|-' t '\in' T" := (has_type t T). Hint Constructors has_type : core. Example has_type_1 : |- test fls zro (scc zro) \in Nat. Proof. apply T_Test. - apply T_Fls. - apply T_Zro. - apply T_Scc. apply T_Zro. Qed. (** Typing is a _conservative_ (_static_) approximation to behavior. In particular, a term can be ill typed even though it steps to something well typed. *) Example has_type_not : ~ ( |- test fls zro tru \in Bool ). Proof. intros Contra. solve_by_inverts 2. Qed. (* ----------------------------------------------------------------- *) (** *** Canonical forms *) (** The following two lemmas capture the fundamental property that the definitions of boolean and numeric values agree with the typing relation. *) Lemma bool_canonical : forall t, |- t \in Bool -> value t -> bvalue t. Proof. intros t HT [Hb | Hn]. - assumption. - destruct Hn as [ | Hs]. + inversion HT. + inversion HT. Qed. Lemma nat_canonical : forall t, |- t \in Nat -> value t -> nvalue t. Proof. intros t HT [Hb | Hn]. - inversion Hb; subst; inversion HT. - assumption. Qed. (* ================================================================= *) (** ** Progress *) (** The typing relation enjoys two critical properties. The first is that well-typed normal forms are not stuck -- or conversely, if a term is well typed, then either it is a value or it can take at least one step. We call this _progress_. *) Theorem progress : forall t T, |- t \in T -> value t \/ exists t', t --> t'. Proof. intros t T HT. induction HT; auto. (* The cases that were obviously values, like T_Tru and T_Fls, were eliminated immediately by auto *) - (* T_Test *) right. destruct IHHT1. + (* t1 is a value *) apply (bool_canonical t1 HT1) in H. destruct H. * exists t2. auto. * exists t3. auto. + (* t1 can take a step *) destruct H as [t1' H1]. exists (test t1' t2 t3). auto. (* FILL IN HERE *) Admitted. (* QUIZ What is the relation between the _progress_ property defined here and the _strong progress_ from [SmallStep]? (1) No difference (2) Progress implies strong progress (3) Strong progress implies progress (4) They are unrelated properties (5) Dunno *) (** This theorem is more interesting than the strong progress theorem that we saw in the [Smallstep] chapter, where _all_ normal forms were values. Here a term can be stuck, but only if it is ill typed. *) (* QUIZ Quick review: In the language defined at the start of this chapter... - Every well-typed normal form is a value. (1) True (2) False *) (* QUIZ In this language... - Every value is a normal form. (1) True (2) False *) (* QUIZ In this language... - The single-step reduction relation is a partial function (i.e., it is deterministic). (1) True (2) False *) (* QUIZ In this language... - The single-step reduction relation is a _total_ function. (1) True (2) False *) (* ================================================================= *) (** ** Type Preservation *) (** The second critical property of typing is that, when a well-typed term takes a step, the result is also a well-typed term. *) (** **** Exercise: 2 stars, standard (finish_preservation) *) Theorem preservation : forall t t' T, |- t \in T -> t --> t' -> |- t' \in T. (** Complete the formal proof of the [preservation] property. (Again, make sure you understand the informal proof fragment in the following exercise first.) *) Proof. intros t t' T HT HE. generalize dependent t'. induction HT; (* every case needs to introduce a couple of things *) intros t' HE; (* and we can deal with several impossible cases all at once *) try solve_by_invert. - (* T_Test *) inversion HE; subst; clear HE. + (* ST_TESTTru *) assumption. + (* ST_TestFls *) assumption. + (* ST_Test *) apply T_Test; try assumption. apply IHHT1; assumption. (* FILL IN HERE *) Admitted. (* ================================================================= *) (** ** Type Soundness *) (** Putting progress and preservation together, we see that a well-typed term can never reach a stuck state. *) Definition multistep := (multi step). Notation "t1 '-->*' t2" := (multistep t1 t2) (at level 40). Corollary soundness : forall t t' T, |- t \in T -> t -->* t' -> ~(stuck t'). Proof. intros t t' T HT P. induction P; intros [R S]. - apply progress in HT. destruct HT; auto. - apply IHP. + apply preservation with (t := x); auto. + unfold stuck. split; auto. Qed. (* QUIZ Suppose we add the following two new rules to the reduction relation: | ST_PrdTru : (prd tru) --> (prd fls) | ST_PrdFls : (prd fls) --> (prd tru) Which of the following properties remain true in the presence of these rules? (Choose 1 for yes, 2 for no.) - Determinism of [step] - Progress - Preservation *) (* QUIZ Suppose, instead, that we add this new rule to the typing relation: | T_TestFunny : forall t2 t3, |- t2 \in Nat -> |- test tru t2 t3 \in Nat Which of the following properties remain true in the presence of these rules? - Determinism of [step] - Progress - Preservation *) (* QUIZ Suppose that we add this new rule to the typing relation: | T_SccBool : forall t, |- t \in Bool -> |- scc t \in Bool Which of the following properties remain true in the presence of this rule? For each one, write either "remains true" or else "becomes false." If a property becomes false, give a counterexample. - Determinism of [step] - Progress - Preservation *) (** Suppose instead that we add this rule: | T_Funny5 : |- prd zro \in Bool Which of the above properties become false in the presence of this rule? For each one that does, give a counter-example. *)