|
| 1 | +module Clase2 |
| 2 | + |
| 3 | +(* Polimorfismo paramétrico y lógica constructiva. *) |
| 4 | + |
| 5 | +(* La identidad polimórfica *) |
| 6 | +val id0_exp : (a:Type) -> a -> a |
| 7 | +let id0_exp = fun (a:Type) -> fun (x:a) -> x |
| 8 | + |
| 9 | +// let id0_exp = fun (a:Type) -> fun (x:a) -> x |
| 10 | +let id_int : int -> int = id0_exp _ |
| 11 | +let id_bool : bool -> bool = id0_exp _ |
| 12 | + |
| 13 | +let _ = assert (id_int 1 == 1) |
| 14 | +let _ = assert (id_bool true == true) |
| 15 | + |
| 16 | +(* El símbolo # marca un argumento * implícito. Estos argumentos |
| 17 | +se insertan automáticamente por el typechecker cuando son requeridos. |
| 18 | +Si hay una única forma de resolverlos, dada otras restricciones en el contexto, |
| 19 | +F* usará esa solución. Si por alguna razón no puede resolverse automáticamente, |
| 20 | +siempre pueden darse de forma explícita usando un # en la aplicación. *) |
| 21 | + |
| 22 | +let id (#a:Type) (x:a) : a = x |
| 23 | +// let id = fun (#a:Type) -> fun (x:a) -> x |
| 24 | +let id_int' : int -> int = id |
| 25 | +let id_bool' : bool -> bool = id |
| 26 | + |
| 27 | +let _ = assert (id 1 == 1) |
| 28 | +let _ = assert (id true == true) |
| 29 | + |
| 30 | +(* Un tipo verdaderemente dependiente *) |
| 31 | +val raro : bool -> Type0 |
| 32 | +let raro (b:bool) : Type = |
| 33 | + if b |
| 34 | + then int |
| 35 | + else string |
| 36 | + |
| 37 | +(* Una función con el tipo `raro`: devuelve un entero o una |
| 38 | +cadena según su argumento. *) |
| 39 | +let f_raro (x:bool) : raro x = |
| 40 | + if x then 123 else "hola" |
| 41 | + |
| 42 | +let _ = assert (f_raro true == 123) |
| 43 | +let _ = assert (f_raro false == "hola") |
| 44 | + |
| 45 | +(* (listas)^n de a *) |
| 46 | +let rec nlist (a:Type) (n:nat) : Type = |
| 47 | + match n with |
| 48 | + | 0 -> a |
| 49 | + | n -> list (nlist a (n-1)) |
| 50 | + |
| 51 | +let rec n_singleton (#a:_) (x:a) (n:nat) : nlist a n = |
| 52 | + match n with |
| 53 | + | 0 -> x |
| 54 | + | n -> [n_singleton x (n-1)] |
| 55 | + |
| 56 | +let _ = assert (n_singleton 1 0 == 1) |
| 57 | +let _ = assert (n_singleton 1 1 == [1]) |
| 58 | +let _ = assert (n_singleton 1 2 == [[1]]) |
| 59 | + |
| 60 | +(* Lógica constructiva *) |
| 61 | + |
| 62 | +(* |
| 63 | +De la librería estándar de F*: |
| 64 | +
|
| 65 | + type tuple2 'a 'b = | Mktuple2 : _1: 'a -> _2: 'b -> tuple2 'a 'b |
| 66 | + let fst (x: tuple2 'a 'b) : 'a = Mktuple2?._1 x |
| 67 | + let snd (x: tuple2 'a 'b) : 'b = Mktuple2?._2 x |
| 68 | +
|
| 69 | + type either a b = |
| 70 | + | Inl : v: a -> either a b |
| 71 | + | Inr : v: b -> either a b |
| 72 | +
|
| 73 | +`a & b` es azúcar para `tuple2 a b` |
| 74 | +`(x,y)` es azúcar para `Mktuple2 x y` |
| 75 | +*) |
| 76 | +type yy (a b : Type) = a & b |
| 77 | +type oo (a b : Type) = either a b |
| 78 | +type falso = |
| 79 | +type verd = falso -> falso |
| 80 | +type no (a : Type) = a -> falso |
| 81 | + |
| 82 | +let vv : verd = id |
| 83 | + |
| 84 | +(* La conjunción conmuta *) |
| 85 | +let comm_yy (#a #b : Type) : yy a b -> yy b a = |
| 86 | + fun p -> (snd p, fst p) |
| 87 | +// fun (x, y) -> (y, x) |
| 88 | + |
| 89 | +(* verd es neutro para la conjunción *) |
| 90 | +let neutro_yy (#a:Type) : yy a verd -> a = |
| 91 | + fun (x, _) -> x |
| 92 | + |
| 93 | +let neutro_yy' (#a:Type) : a -> yy a verd = |
| 94 | + fun (x:a) -> (x, vv) |
| 95 | + |
| 96 | +(* La disjunción conmuta *) |
| 97 | +(* `function` es azúcar para `fun` con un pattern matching inmediato al argumento. *) |
| 98 | +let comm_oo (#a #b : Type) : oo a b -> oo b a = |
| 99 | + function |
| 100 | + | Inl x -> Inr x |
| 101 | + | Inr y -> Inl y |
| 102 | + |
| 103 | +(* Principio de explosión: falso no tiene constructores, |
| 104 | +así que con un match vacío podemos demostrar cualquier cosa *) |
| 105 | +let ex_falso (#a:Type) (f : falso) : a = |
| 106 | + match f with |
| 107 | + |
| 108 | +(* Demostrar *) |
| 109 | +let neu1 (#a:Type) : oo a falso -> a = |
| 110 | + admit() |
| 111 | + |
| 112 | +(* Demostrar *) |
| 113 | +let neu2 (#a:Type) : a -> oo a falso = |
| 114 | + admit() |
| 115 | + |
| 116 | +(* Distribución de `yy` sobre `oo`, en ambas direcciones *) |
| 117 | +let distr_yyoo_1 (#a #b #c : Type) |
| 118 | + : yy a (oo b c) -> oo (yy a b) (yy a c) |
| 119 | + // a /\ (b \/ c) ==> (a /\ b) \/ (a /\ c) |
| 120 | + // a * (b + c) ==> (a * b) + (a * c) |
| 121 | += |
| 122 | + fun (x, yz) -> |
| 123 | + match yz with |
| 124 | + | Inl y -> Inl (x, y) |
| 125 | + | Inr z -> Inr (x, z) |
| 126 | + |
| 127 | +let distr_yyoo_2 (#a #b #c : Type) |
| 128 | + : oo (yy a b) (yy a c) -> yy a (oo b c) |
| 129 | += |
| 130 | + admit() |
| 131 | + |
| 132 | +let distr_ooyy_1 (#a #b #c : Type) |
| 133 | + : oo a (yy b c) -> yy (oo a b) (oo a c) |
| 134 | += |
| 135 | + admit() |
| 136 | + |
| 137 | +let distr_ooyy_2 (#a #b #c : Type) |
| 138 | + : yy (oo a b) (oo a c) -> oo a (yy b c) |
| 139 | += |
| 140 | + admit() |
| 141 | + |
| 142 | +let modus_tollens (#a #b : Type) |
| 143 | + : (a -> b) -> (no b -> no a) |
| 144 | += |
| 145 | + admit() |
| 146 | + (* Vale la recíproca? *) |
| 147 | + |
| 148 | +let modus_tollendo_ponens (#a #b : Type) |
| 149 | + : (oo a b) -> (no a -> b) |
| 150 | += |
| 151 | + admit() |
| 152 | + (* Vale la recíproca? *) |
| 153 | + |
| 154 | +let modus_ponendo_tollens (#a #b : Type) |
| 155 | + : no (yy a b) -> (a -> no b) |
| 156 | += |
| 157 | + admit() |
| 158 | + (* Vale la recíproca? *) |
| 159 | + |
| 160 | +(* Declare y pruebe, si es posible, las leyes de De Morgan |
| 161 | +para `yy` y `oo`. ¿Son todas intuicionistas? *) |
| 162 | + |
| 163 | +let demorgan1_ida (#a #b : Type) : oo (no a) (no b) -> no (yy a b) = |
| 164 | + admit() |
| 165 | + |
| 166 | +let demorgan1_vuelta (#a #b : Type) : no (yy a b) -> oo (no a) (no b) = |
| 167 | + admit() |
| 168 | + |
| 169 | +let demorgan2_ida (#a #b : Type) : yy (no a) (no b) -> no (oo a b) = |
| 170 | + admit() |
| 171 | + |
| 172 | +let demorgan2_vuelta (#a #b : Type) : no (oo a b) -> yy (no a) (no b) = |
| 173 | + admit() |
| 174 | + |
| 175 | + |
| 176 | + (* P y no P no pueden valer a la vez. *) |
| 177 | +let no_contradiccion (#a:Type) : no (yy a (no a)) = |
| 178 | + fun (x, f) -> f x |
| 179 | + |
| 180 | +(* Mientras "quede" una negación, sí podemos eliminar doble |
| 181 | +negaciones. Pero no podemos llegar a una prueba de a. |
| 182 | +
|
| 183 | +Ver también el embebimiento de lógica clásica en lógica intuicionista |
| 184 | +via doble negación (spoiler: p se embebe como no (no p), y resulta equivalente |
| 185 | +a la lógica clásica. *) |
| 186 | +let elim_triple_neg (#a:Type) : no (no (no a)) -> no a = |
| 187 | + fun f a -> f (fun g -> g a) |
| 188 | + |
| 189 | +(* Ejercicio. ¿Se puede en lógica intuicionista? *) |
| 190 | +let ley_impl1 (p q : Type) : (p -> q) -> oo (no p) q = |
| 191 | + admit() |
| 192 | + |
| 193 | +(* Ejercicio. ¿Se puede en lógica intuicionista? *) |
| 194 | +let ley_impl2 (p q : Type) : oo (no p) q -> (p -> q) = |
| 195 | + admit() |
| 196 | + |
| 197 | +(* Ejercicio. ¿Se puede en lógica intuicionista? *) |
| 198 | +let ley_impl3 (p q : Type) : no (p -> q) -> yy p (no q) = |
| 199 | + admit() |
| 200 | + |
| 201 | +(* Ejercicio. ¿Se puede en lógica intuicionista? *) |
| 202 | +let ley_impl4 (p q : Type) : yy p (no q) -> no (p -> q) = |
| 203 | + admit() |
| 204 | + |
| 205 | +(* Tipos para axiomas clásicos *) |
| 206 | +type eliminacion_doble_neg = (#a:Type) -> no (no a) -> a |
| 207 | +type tercero_excluido = (a:Type) -> oo a (no a) |
| 208 | + |
| 209 | +(* Ejercicio *) |
| 210 | +let lte_implica_edn (lte : tercero_excluido) (#a:Type) : eliminacion_doble_neg = |
| 211 | + admit() |
| 212 | + |
| 213 | +(* Ejercicio. ¡Difícil! *) |
| 214 | +let edn_implica_lte (edn : eliminacion_doble_neg) (#a:Type) : oo a (no a) = |
| 215 | + admit() |
| 216 | + |
| 217 | +(* Ejercicio: ¿la ley de Peirce es intuicionista o clásica? |
| 218 | +Demuestrelá sin axiomas para demostrar que es intuicionista, |
| 219 | +o demuestre que implica el tercero excluido para demostrar que |
| 220 | +es clásica. *) |
| 221 | + |
| 222 | +type peirce = (#a:Type) -> (#b:Type) -> ((a -> b) -> a) -> a |
| 223 | + |
| 224 | +let lte_implica_peirce (lte : tercero_excluido) : peirce = |
| 225 | + admit() |
| 226 | + |
| 227 | +let peirce_implica_lte (pp : peirce) : tercero_excluido = |
| 228 | + admit() |
0 commit comments