Mercurial > cpdt > repo
comparison src/Universes.v @ 377:252ba054a1cd
One more example of avoiding axioms (getNat)
author | Adam Chlipala <adam@chlipala.net> |
---|---|
date | Wed, 28 Mar 2012 13:20:50 -0400 |
parents | 3322367e955d |
children | 6413675f8e04 |
comparison
equal
deleted
inserted
replaced
376:3b36b1e05b4e | 377:252ba054a1cd |
---|---|
1 (* Copyright (c) 2009-2011, Adam Chlipala | 1 (* Copyright (c) 2009-2012, Adam Chlipala |
2 * | 2 * |
3 * This work is licensed under a | 3 * This work is licensed under a |
4 * Creative Commons Attribution-Noncommercial-No Derivative Works 3.0 | 4 * Creative Commons Attribution-Noncommercial-No Derivative Works 3.0 |
5 * Unported License. | 5 * Unported License. |
6 * The license text is available at: | 6 * The license text is available at: |
7 * http://creativecommons.org/licenses/by-nc-nd/3.0/ | 7 * http://creativecommons.org/licenses/by-nc-nd/3.0/ |
8 *) | 8 *) |
9 | 9 |
10 (* begin hide *) | 10 (* begin hide *) |
11 Require Import List. | |
12 | |
11 Require Import DepList CpdtTactics. | 13 Require Import DepList CpdtTactics. |
12 | 14 |
13 Set Implicit Arguments. | 15 Set Implicit Arguments. |
14 (* end hide *) | 16 (* end hide *) |
15 | 17 |
1014 Print Assumptions proj1_again. | 1016 Print Assumptions proj1_again. |
1015 (** << | 1017 (** << |
1016 Closed under the global context | 1018 Closed under the global context |
1017 >> | 1019 >> |
1018 | 1020 |
1019 This example illustrates again how some of the same design patterns we learned for dependently typed programming can be used fruitfully in theorem statements. *) | 1021 This example illustrates again how some of the same design patterns we learned for dependently typed programming can be used fruitfully in theorem statements. |
1022 | |
1023 %\medskip% | |
1024 | |
1025 To close the chapter, we consider one final way to avoid dependence on axioms. Often this task is equivalent to writing definitions such that they %\emph{%#<i>#compute#</i>#%}%. That is, we want Coq's normal reduction to be able to run certain programs to completion. Here is a simple example where such computation can get stuck. In proving properties of such functions, we would need to apply axioms like %\index{axiom K}%K manually to make progress. | |
1026 | |
1027 Imagine we are working with %\index{deep embedding}%deeply embedded syntax of some programming language, where each term is considered to be in the scope of a number of free variables that hold normal Coq values. To enforce proper typing, we will need to model a Coq typing environment somehow. One natural choice is as a list of types, where variable number [i] will be treated as a reference to the [i]th element of the list. *) | |
1028 | |
1029 Section withTypes. | |
1030 Variable types : list Set. | |
1031 | |
1032 (** To give the semantics of terms, we will need to represent value environments, which assign each variable a term of the proper type. *) | |
1033 | |
1034 Variable values : hlist (fun x : Set => x) types. | |
1035 | |
1036 (** Now imagine that we are writing some procedure that operates on a distinguished variable of type [nat]. A hypothesis formalizes this assumption, using the standard library function [nth_error] for looking up list elements by position. *) | |
1037 | |
1038 Variable natIndex : nat. | |
1039 Variable natIndex_ok : nth_error types natIndex = Some nat. | |
1040 | |
1041 (** It is not hard to use this hypothesis to write a function for extracting the [nat] value in position [natIndex] of [values], starting with two helpful lemmas, each of which we finish with [Defined] to mark the lemma as transparent, so that its definition may be expanded during evaluation. *) | |
1042 | |
1043 Lemma nth_error_nil : forall A n x, | |
1044 nth_error (@nil A) n = Some x | |
1045 -> False. | |
1046 destruct n; simpl; unfold error; congruence. | |
1047 Defined. | |
1048 | |
1049 Implicit Arguments nth_error_nil [A n x]. | |
1050 | |
1051 Lemma Some_inj : forall A (x y : A), | |
1052 Some x = Some y | |
1053 -> x = y. | |
1054 congruence. | |
1055 Defined. | |
1056 | |
1057 Fixpoint getNat (types' : list Set) (values' : hlist (fun x : Set => x) types') | |
1058 (natIndex : nat) : (nth_error types' natIndex = Some nat) -> nat := | |
1059 match values' with | |
1060 | HNil => fun pf => match nth_error_nil pf with end | |
1061 | HCons t ts x values'' => | |
1062 match natIndex return nth_error (t :: ts) natIndex = Some nat -> nat with | |
1063 | O => fun pf => | |
1064 match Some_inj pf in _ = T return T with | |
1065 | refl_equal => x | |
1066 end | |
1067 | S natIndex' => getNat values'' natIndex' | |
1068 end | |
1069 end. | |
1070 End withTypes. | |
1071 | |
1072 (** The problem becomes apparent when we experiment with running [getNat] on a concrete [types] list. *) | |
1073 | |
1074 Definition myTypes := unit :: nat :: bool :: nil. | |
1075 Definition myValues : hlist (fun x : Set => x) myTypes := | |
1076 tt ::: 3 ::: false ::: HNil. | |
1077 | |
1078 Definition myNatIndex := 1. | |
1079 | |
1080 Theorem myNatIndex_ok : nth_error myTypes myNatIndex = Some nat. | |
1081 reflexivity. | |
1082 Defined. | |
1083 | |
1084 Eval compute in getNat myValues myNatIndex myNatIndex_ok. | |
1085 (** %\vspace{-.15in}%[[ | |
1086 = 3 | |
1087 ]] | |
1088 | |
1089 We have not hit the problem yet, since we proceeded with a concrete equality proof for [myNatIndex_ok]. However, consider a case where we want to reason about the behavior of [getNat] %\emph{%#<i>#independently#</i>#%}% of a specific proof. *) | |
1090 | |
1091 Theorem getNat_is_reasonable : forall pf, getNat myValues myNatIndex pf = 3. | |
1092 intro; compute. | |
1093 (** | |
1094 << | |
1095 1 subgoal | |
1096 >> | |
1097 %\vspace{-.3in}%[[ | |
1098 pf : nth_error myTypes myNatIndex = Some nat | |
1099 ============================ | |
1100 match | |
1101 match | |
1102 pf in (_ = y) | |
1103 return (nat = match y with | |
1104 | Some H => H | |
1105 | None => nat | |
1106 end) | |
1107 with | |
1108 | eq_refl => eq_refl | |
1109 end in (_ = T) return T | |
1110 with | |
1111 | eq_refl => 3 | |
1112 end = 3 | |
1113 ]] | |
1114 | |
1115 Since the details of the equality proof [pf] are not known, computation can proceed no further. A rewrite with axiom K would allow us to make progress, but we can rethink the definitions a bit to avoid depending on axioms. *) | |
1116 | |
1117 Abort. | |
1118 | |
1119 (** Here is a definition of a function that turns out to be useful, though no doubt its purpose will be mysterious for now. A call [update ls n x] overwrites the [n]th position of the list [ls] with the value [x], padding the end of the list with extra [x] values as needed to ensure sufficient length. *) | |
1120 | |
1121 Fixpoint copies A (x : A) (n : nat) : list A := | |
1122 match n with | |
1123 | O => nil | |
1124 | S n' => x :: copies x n' | |
1125 end. | |
1126 | |
1127 Fixpoint update A (ls : list A) (n : nat) (x : A) : list A := | |
1128 match ls with | |
1129 | nil => copies x n ++ x :: nil | |
1130 | y :: ls' => match n with | |
1131 | O => x :: ls' | |
1132 | S n' => y :: update ls' n' x | |
1133 end | |
1134 end. | |
1135 | |
1136 (** Now let us revisit the definition of [getNat]. *) | |
1137 | |
1138 Section withTypes'. | |
1139 Variable types : list Set. | |
1140 Variable natIndex : nat. | |
1141 | |
1142 (** Here is the trick: instead of asserting properties about the list [types], we build a %``%#"#new#"#%''% list that is %\emph{%#<i>#guaranteed by construction#</i>#%}% to have those properties. *) | |
1143 | |
1144 Definition types' := update types natIndex nat. | |
1145 | |
1146 Variable values : hlist (fun x : Set => x) types'. | |
1147 | |
1148 (** Now a bit of dependent pattern matching helps us rewrite [getNat] in a way that avoids any use of equality proofs. *) | |
1149 | |
1150 Fixpoint getNat' (types'' : list Set) (natIndex : nat) | |
1151 : hlist (fun x : Set => x) (update types'' natIndex nat) -> nat := | |
1152 match types'' with | |
1153 | nil => fun vs => hhd vs | |
1154 | t :: types0 => | |
1155 match natIndex return hlist (fun x : Set => x) | |
1156 (update (t :: types0) natIndex nat) -> nat with | |
1157 | O => fun vs => hhd vs | |
1158 | S natIndex' => fun vs => getNat' types0 natIndex' (htl vs) | |
1159 end | |
1160 end. | |
1161 End withTypes'. | |
1162 | |
1163 (** Now the surprise comes in how easy it is to %\emph{%#<i>#use#</i>#%}% [getNat']. While typing works by modification of a types list, we can choose parameters so that the modification has no effect. *) | |
1164 | |
1165 Theorem getNat_is_reasonable : getNat' myTypes myNatIndex myValues = 3. | |
1166 reflexivity. | |
1167 Qed. | |
1168 | |
1169 (** The same parameters as before work without alteration, and we avoid use of axioms. *) |