Vous êtes sur la page 1sur 14

Logica Computacional 2016-2, nota de clase 13

El Isomorfismo de Curry-Howard
Favio Ezequiel Miranda Perea
Araceli Liliana Reyes Cabello
Lourdes Del Carmen Gonzalez Huesca
23 de mayo de 2016
Facultad de Ciencias UNAM

1.

Un lenguaje para expresiones aritm


eticas y booleanas

A continuaci
on presentamos un lenguaje para expresiones aritmeticas y booleanas que incluye
las operaciones de suma, producto, orden, un test para cero y la negacion booleana.
Las expresiones del lenguaje se definen como sigue:
e ::= x | n | true | false |
e+e|ee
e < e | iszero e | not e
Ejemplos de expresiones del lenguaje son:
3+y
not(iszero 9)
iszero 3 < not(2 + 4)
not false
not(x + 1)
iszero false
not 7 y
7<x+y
Se observa que todas son expresiones sintacticamente correctas pero algunas de ellas no tienen
sentido desde el punto de vista sem
antico, es decir, no es posible asignarles uno de los tipos posibles
para el lenguaje que son Nat o Bool. Por ejemplo not(8 + 2) o iszero false. Ademas hay expresiones
en donde no resulta claro si son v
alidas o no, por ejemplo x + 2 puede o no ser valida dependiendo
de si x representa a un n
umero o a un booleano, lo mismo sucede con not(iszero x) o con x < y + 1.
1

1.1.

Int
erprete

Un interprete para el lenguaje es simplemente una funcion que devuelve un natural o un booleano
que resulta de evaluar una expresi
on e. La definicion recursiva de esta funcion
eval : Exp N B
donde N = {0, 1, . . .} y B = {t, f } es:
eval
eval
eval
eval
eval
eval
eval
eval

n = n
true = t
false = f
(e1 + e2) = eval e1 +
(e1 * e2) = eval e1 *
(e1 < e2) = (eval e1)
(not e) = (eval e)
(iszero e) = isz (eval

eval e2
eval e2
< (eval e2)
e)

donde los smbolos del lado derecho +, , < denotan las operaciones usuales mientras que del
lado izquierdo son u
nicamente smbolos que forman parte de las expresiones. Omitmos aqu el
uso de variables por simplicidad en la presentacion. Para agregar variables es necesario agregar un
estado como argumento de entrada al interprete, el cual se encargara de evaluar variables.
Se observa que la funci
on de evaluacion as definida resulta una funcion parcial puesto que la
evaluacion de expresiones como (35)+not false no tiene sentido ya que no sabemos sumar 15+true.
Una manera de evitar estos errores es verificando previamente si la expresion es coherente para
lo cual podemos usar la deducci
on natural.

1.2.

Eliminaci
on de expresiones sem
anticamente incorrectas

Sea el conjunto de las siguientes formulas:


N at(n)
Bool(true)
Bool(f alse)
xy(N at(x) N at(y) N at(x + y))
xy(N at(x) N at(y) N at(x y))
xy(N at(x) N at(y) Bool(x < y))
xy(Bool(x) Bool(not x))
xy(N at(x) Bool(iszero x))
Podemos verificar si una expresi
on e es semanticamente correcta si es posible clasificarla como
natural o booleano derivando ` N at(e) o ` Bool(e). Por ejemplo
` not(iszero(2 + 3 4))

6` Bool(iszero(3 7) + 4)

Ademas si hay variables debemos suponer de antemano si representan n


umeros o booleanos. Por
ejemplo
, N at(x) ` Bool(x < 5)
, Bool(z) 6` N at(z + 6)
2

Esta clase de verificaciones son exactamente lo que hace un sistema de tipos en lenguajes de
programacion.

2.

Sistemas de tipos

Un sistema de tipos es un formalismo logico que impone ciertas restricciones en la formaci


on
de programas de un lenguaje de programacion. Las expresiones del lenguaje se clasifican mediante
tipos que dictan como pueden usarse en combinacion con otras expresiones. Intuitivamente el tipo
de una expresi
on predice la forma de su valor, por ejemplo, la expresion e1 + e2 donde e1 y e2 son
expresiones numericas debe ser una expresion numerica nuevamente. Por otra parte si intentamos
sumar una expresi
on numerica con una expresion booleana digamos true +7 dicha expresion debe
ser prohibida ya que genera un error de tipos1 .
El uso de sistemas de tipos en el dise
no de un lenguaje de programacion tiene las siguientes
ventajas:
Permite descubrir errores de programacion tempranamente.
Ofrece seguridad, un programa correctamente tipado no puede funcionar mal.
Soporta abstracci
on, importante para la descripcion de interfaces.
Los tipos documentan un programa de manera mas simple y manejable que los comentarios.
Los lenguajes tipados pueden implementarse de manera mas clara y eficiente.
Para decidir si la expresi
on es semanticamente correcta o no, los lenguajes de programaci
on
emplean contextos de declaraci
on de variables que involucran a un predicado binario infijo denotado x : T, que relaciona a una variable x con un tipo T. Esta declaracion significa que la
variable x representa a un valor de tipo T. Un contexto es entonces un conjunto de la forma
= {x1 : T1 , . . . , xn : Tn } donde todas las variables xi son distintas.
Por ejemplo si = {x : Nat, y : Bool} entonces las expresiones x + 2 y not y son aceptadas, mientras que y < 2 y not x son rechazadas para su evaluacion. Para formalizar la verificacion de tipos
correctos se utiliza una relaci
on ternaria que involucra a un contexto , a una expresion cualquiera
del lenguaje e y a un tipo T.
Dicha relacion se escribe como ` e : T y se lee como la expresion e es de tipo T en el contexto
.
Esta relaci
on se conoce como relaci
on de tipado y se define recursivamente mediante las siguientes
reglas de inferencia:
, x : T ` x : T
` n : Nat
1

(T N um)

(V ar)

` e1 : Nat ` e2 : Nat
(T Sum)
` e1 + e2 : Nat

Type-checking error

` e1 : Nat ` e2 : Nat
(T P rod)
` e1 e2 : Nat

` true : Bool

(T true)

` false : Bool

(T f alse)

` e1 : Nat ` e2 : Nat
(T men)
` e1 < e2 : Bool

` e : Nat
` e : Bool
(T isz)
(T not)
` iszero e : Bool
` not e : Bool
Mediante estas reglas podemos cerciorarnos por ejemplo de que si x : Nat entonces iszero(x + 2) :
Bool como sigue:
1. x : Nat ` x : Nat (V ar)
2. x : Nat ` 2 : Nat (T N um)
3. x : Nat ` x + 2 : Nat (T Sum) 1, 2
4. x : Nat ` iszero(x + 2) : Nat (T isz) 4
Veamos otro ejemplo, esta vez tipando la expresion not(2 + x < y) en el contexto = {x :
Nat, y : Nat}
1. x : Nat, y : Nat ` x : Nat (V ar)
2. x : Nat, y : Nat ` 2 : Nat (T N um)
3. x : Nat, y : Nat ` 2 + x : Nat (T Sum) 1, 2
4. x : Nat, y : Nat ` y : Nat (V ar)
5. x : Nat, y : Nat ` 2 + x < y : Bool (T men) 3, 4
6. x : Nat, y : Nat ` not(2 + x < y) : Bool (T neg) 5

3.

Isomorfismo de Curry-Howard

Como se observa los sistemas de tipos son muy similares a los sistemas de deduccion natural
con contextos que ya hemos estudiado. De hecho los sistemas de deduccion natural pueden verse,
desde el punto de vista computacional, como un sistema de tipos para un prototipo de lenguaje de
programacion funcional mediante la llamada correspondencia de Curry-Howard, tambien conocida
como paradigma de derivaciones como programas o proposiciones como tipos. La idea a grandes
rasgos es:
Las formulas de la l
ogica corresponden a tipos para un lenguaje de programacion.
Las pruebas o derivaciones en la logica corresponden a los pasos que el verificador de tipos
realiza para mostrar que cierta expresion o programa del lenguaje de programacion est
a bien
tipada.
Por lo tanto, verificar si una prueba es correcta en un contexto dado corresponde a verificar
si un programa tiene un tipo v
alido en el contexto dado.
4

4.

Reglas de inferencia con codificaci


on de pruebas

La relaci
on de inferencia ` A se modifica anotando a cada prueba de un secuente ` A
mediante una expresi
on t que que corresponde a un programa de un prototipo de lenguaje de programacion, esta expresi
on t resulta ser tambien un codigo de la prueba cuyo secuente final es ` A.
De esta manera obtenemos una relacion ` t : A donde = {x1 : A1 , . . . , xn : An } es un
contexto de declaraci
on de variables xi : Ai consideradas locales. En este caso no solo suponemos
una formula Ai sino que tambien suponemos que existe una prueba xi de Ai . La nueva relaci
on
entre contextos , expresiones o c
odigos t y formulas A, puede entenderse desde dos puntos de vista
distintos:
Logicamente: ` t : A significa que la formula A es derivable a partir de las hipotesis y t
es un c
odigo de prueba para la derivacion ` A.
Computacionalmente: ` t : A significa que t es un programa con tipo A cuyas variables
locales est
an declaradas en .
La nueva relaci
on de inferencia se define recursivamente a partir de la regla de inicio:
, x : A ` x : A (Hip)
mediante reglas de introducci
on y eliminacion para cada conectivo
Implicaci
on: el conectivo corresponde al tipo de funciones.
, x : A ` t : B
`f :AB `t:A
( I)
( E)
` fun(x : A.t) : A B
`ft:B
Conjunci
on: el conectivo corresponde al tipo , es decir al producto cartesiano de dos tipos.
`t:A `s:B
(I)
` ht, si : A B

`t:AB
(2 E)
` fst t : A

`t:AB
(1 E)
` snd t : B

Disyunci
on: el conectivo corresponde al tipo +, es decir a la union disjunta de dos tipos.
`t:A
(1 I)
` inl t : A B

`t:B
(2 I)
` inr t : A B

` r : A B , x : A ` s : C , y : B ` t : C
(E)
` case r of inl x s | inr y t : C
Falso: la constante de falsedad corresponde a un tipo vaco.
`r:
(E)
` abort r : A

5.

Ejemplos

En los siguientes ejemplos se trata de hallar el programa t que codifique la prueba correspondiente. Como ejercicios el lector debe justificar cada paso y/o agregar algunos pasos faltantes.
`t:AA
1. x : A ` x : A
2. ` fun(x : A.x) : A A
`t:AAB
1. x : A ` x : A
2. x : A ` inl x : A B
3. ` fun(x : A. inl x) : A A B
`t:AB B
1. x : A B ` x : A B
2. x : A B ` snd x : B
3. ` fun(x : A B. snd x) : A B B
f : A B, g : B C ` t : A C
1. f : A B, g : B C, x : A ` f : A B
2. f : A B, g : B C, x : A ` g : B C
3. f : A B, g : B C, x : A ` x : A
4. f : A B, g : B C, x : A ` f x : B
5. f : A B, g : B C, x : A ` g(f x) : C
6. f : A B, g : B C ` fun(x : A.g(f x)) : A C
`: t : B (A B)
1. x : B, y : A ` x : B
2. x : B ` fun(y : A.x) : A B
3. ` fun(x : B. fun(y : A.x)) : B (A B)
` t : (A B C) (A B C)
1. f : A B C, x : A, y : B ` f : A B C
2. f : A B C, x : A, y : B ` x : A
3. f : A B C, x : A, y : B ` y : B
4. f : A B C, x : A, y : B ` hx, yi : A B
5. f : A B C, x : A, y : B ` f hx, yi : C
6. f : A B C, x : A ` fun(y : B.f hx, yi) : B C
6


7. f : A B C ` fun x : A. fun(y : B.f hx, yi) : A B C


8. ` fun f : A B C. fun x : A. fun(y : B.f hx, yi) : (A B C) A B C
f :AB C `t:AB C
1. f : A B C, x : A B ` f : A B C
2. f : A B C, x : A B ` f : A B C
3. f : A B C, x : A B ` x : A B
4. f : A B C, x : A B ` fst x : A
5. f : A B C, x : A B ` snd x : B
6. f : A B C, x : A B ` f (fst x) : B C
7. f : A B C, x : A B ` f (fst x)(snd x) : C

8. f : A B C ` fun x : A B.f (fst x)(snd x) : A B C
f :AB C `t:AC
1. f : A B C, x : A ` f : A B C
2. f : A B C, x : A ` x : A
3. f : A B C, x : A ` inl x : A B
4. f : A B C, x : A ` f (inl x) : C
5. f : A B C ` fun(x : A.f (inl x)) : A C
x : A B, f : A C, g : B C ` t : C
1. x : A B, f : A C, g : B C ` x : A B
2. x : A B, f : A C, g : B C, y : A ` f y : C
3. x : A B, f : A C, g : B C, z : B ` gz : C
4. x : A B, f : A C, g : B C ` ( case x of inl y f y | inr z gz) : C
f : A B, g : C D, x : A C ` t : B D
1. f : A B, g : C D, x : A C ` x : A C
2. f : A B, g : C D, x : A C, y : A ` inl(f y) : B D
3. f : A B, g : C D, x : A C, z : C ` inr(gz) : B D
4. f : A B, g : C D, x : A C ` ( case x of inl y inl(f y) | inr z inr(gz)) : B D
x : (A C) (B C), f : (A B) ` t : C
1. x : (A C) (B C), f : (A B) ` fst x : A C
2. x : (A C) (B C), f : (A B) ` snd x : B C
3. x : (A C) (B C), f : (A B), y : A ` f y : B
4. x : (A C) (B C), f : (A B), y : A ` (snd x)(f y) : C
7

5. x : (A C) (B C), f : (A B), z : C ` z : C
6. x : (A C) (B C), f : (A B) ` ( case x of inl y inl(snd x)(f y) | inr z z) : C
x : A (B C) ` t : (A B) (A C)
1. x : A (B C) ` fst x : A
2. x : A (B C) ` snd x : B C
3. x : A (B C), y : B ` hfst x, yi : A B
4. x : A (B C), y : B ` inlhfst x, yi : (A B) (A C)
5. x : A (B C), z : C ` inrhfst x, zi : (A B) (A C)
6. x : A(BC) ` ( case snd x of inl y inlhfst x, yi | inr z inrhfst x, zi) : (AB)(AC)
x : (A B) (A C) ` t : A (B C)
1. x : (A B) (A C), y : A B ` inl(snd y) : B C
2. x : (A B) (A C), y : A B ` hfst y, inl(snd y)i : A (B C)
3. x : (A B) (A C), z : A C ` hfst z, inr(snd z)i : A (B C)
4. x : (A B) (A C) ` ( case x of inl y hfst y, inl(snd y)i | inr z hfst z, inr(snd z)i :
A (B C)
x : A B, f : B C D, g : A C ` t : D
1. x : A B, f : B C D, g : A C, y : A ` inr(gy) : B C
2. x : A B, f : B C D, g : A C, y : A ` f inr(gy) : D
3. x : A B, f : B C D, g : A C, z : B ` f (inl z) : D
4. x : A B, f : B C D, g : A C ` ( case x of inl y f inr(gy) | inr z f (inl z) : D

6.

Pruebas redundantes
Dadas las derivaciones ` fun(x : A.e) : A B y ` r : A construir una derivaci
on de
`? : B.
La soluci
on que salta a la vista es ` fun(x : A.e) r : B
Sin embargo de las reglas y la prueba dada de A B, sabemos que previamente
debio obtenerse la prueba , x : A ` e : B puesto que la regla usada fue ( I). Ahora
bien, observese que como ya tenemos una prueba ` r : A, no es necesario suponer
x : A puesto que en la prueba codificada por e podemos sustituir cada prueba x de
A por la prueba dada r, obteniendo as una prueba de B sin necesidad de usar el
modus ponens, a saber ` e[x := r] : B.
Dada la derivaci
on ` he1 , e2 i : A B construir una prueba ` ? : A.
La respuesta m
as inmediata es ` fsthe1 , e2 i : A.
Pero observese que para construir la prueba codificada por fsthe1 , e2 i antes tuvo que
construirse una prueba codificada por e1 que tiene que ser ` e1 : A puesto que la
regla utilizada fue (I).
8

De lo anterior se observa que las primeras pruebas son redundantes y podemos simplificarlas
como sigue:
fun(x : A.e) r se simplifica a e[x := r]
fsthe1 , e2 i se simplifica a e1 .
De la misma manera podemos justificar las siguientes simplificaciones
sndhe1 , e2 i se simplifica a e2 .
case (inl r) of inl x s | inr y t se simplifica a s[x := r]
case (inr r) of inl x s | inr y t se simplifica a t[x := r]
Estas reglas de simplificaci
on pueden utilizarse como reglas de evaluacion de las expresiones de
un lenguaje de programaci
on. En conclusion las pruebas redundantes de la logica y su simplificaci
on
corresponden a un proceso de evaluaci
on de expresiones en un lenguaje de programacion.

6.1.

Compilaci
on de expresiones aritm
eticas y booleanas

Presentamos un ejemplo de compilacion del lenguaje de expresiones aritmeticas y booleanas a


una maquina abstracta de pila. Nos interesa en particular formalizar la prueba de la correctud del
proceso de compilaci
on mediante deduccion natural.
Especificaci
on del lenguaje objeto: se trata de un lenguaje de instrucciones primitivas
i ::= n | t | f | + | | < | not | iszero
de manera que una instrucci
on es un valor natural o booleano o bien un operador del lenguaje
fuente de expresiones aritmeticas y booleanas
Programas: un programa es una lista2 de instrucciones p = [i1 , . . . , in ]
Memoria: la memoria es una lista de valores s = [v1 , . . . , vn ] donde vi {n, t, f }
Ejecuci
on de una instrucci
on: la funcion de ejecucion de una instruccion ej recibe una instruccion i y una memoria s devolviendo la memoria resultante al ejecutar la instruccion.
ej
ej
ej
ej
ej
ej
ej
ej
2

n s = (n:s)
true s = (t:s)
false s = (f:s)
+ (v1:v2:s) = (v1+v2) : s
* (v1:v2:s) = (v1*v2) : s
< (v1:v2:s) = (v1<v2) : s
not (v:s) = ( v) : s
iszero (v:s) = (isz v) : s

En realidad es una pila y elegimos implementarla como una lista, lo mismo sucede con la memoria

donde del lado derecho de las ecuaciones nos referimos a las operaciones binarias +, ::
N N N, <: N N B y a las operaciones unarias : B B, isz : N B
Ejecuci
on de un programa: ejecutar un programa p en la memoria dada s devuelve la memoria
obtenida al ejecutar en orden todas instrucciones de p.
ejp nil s = s
ejp (i:p) s = ejp p (ej i s)

Compilaci
on de una expresi
on en un programa: el proceso de compilacion convierte una expresion e en un programa.
comp
comp
comp
comp
comp
comp
comp
comp

n = [n]
true = [t]
false = [f]
(e1+e2) = comp e2 ++ comp e1 ++ [+]
(e1*e2) = comp e2 ++ comp e1 ++ [*]
(e1<e2) = comp e2 ++ comp e1 ++ [<]
(not e) = comp e ++ [not]
(iszero e) = comp e ++ [iszero]

donde +
+ es la funci
on de concatenacion de listas. Porque en los casos de operadores binarios
queda el programa resultado de compilar la segunda expresion e2 al inicio de la lista?
Correctud del compilador: la memoria resultado de ejecutar el programa p obtenido al compilar
la expresi
on e con la memoria vaca coincide con la memoria cuyo u
nico valor es la evaluaci
on
de la expresi
on e
e (ejp (comp e) nil = [eval e])

Por supuesto en todas las definiciones anteriores estamos suponiendo que las expresiones de
entrada son coherentes en el sentido de que cualquier operacion estara bien definida. Es decir,
estamos suponiendo que el proceso de verificacion previa fue hecho por el sistema de tipos.
Por lo que el cuantificador e se refiere u
nicamente a todas las expresiones semanticamente
correctas.

6.2.

Prueba de la correctud (informal)

Para probar la correctud del compilador vamos a probar algo mas general:
e p s ejp ( comp e

10

++

p) s =


ejp p (eval e:s)

de esta propiedad la correctud del compilador resulta un corolario tomando p = nil, s = nil.
La prueba es por inducci
on sobre las expresiones. Analizamos aqu un caso base y dos casos
inductivos:
Base e = n: P.D. ps(ejp (comp n ++ p) s = ejp p (eval n : s)).
ejp (comp n ++ p) s =
=
=
=
=

ejp ([n] ++ p) s
ejp (n : p) s
ejp p (ej n s)
ejp p (n : s)
ejp p (eval n : s)

Paso inductivo e = e1 e2 .
I.H.1.: ps(ejp (comp e1 +
+ p) s = ejp p (eval e1 : s))
I.H.2.: ps(ejp (comp e2 +
+ p) s = ejp p (eval e2 : s))
Queremos demostrar que:
ps(ejp (comp(e1 e2 ) ++ p) s = ejp p (eval(e1 e2 ) : s))
ejp (comp(e1 e2 ) +
+ p) s =
=
=Asoc ++
=I.H.2
=Asoc ++
=I.H.1
=
=
=
=

ejp ((comp e2 ++ comp e1 ++[]) ++ p) s


ejp ((comp e2 ++(comp e1 ++[] ++ p)) s
ejp ((comp e2 ++(comp e1 ++[] ++ p)) s
ejp (comp e1 ++[] ++ p)) (eval e2 : s)
ejp (comp e1 ++([] ++ p)) (eval e2 : s)
ejp ([] ++ p) (eval e1 : eval e2 : s)
ejp ( : p) (eval e1 : eval e2 : s)
ejp p (ej [] (eval e1 : eval e2 : s))
ejp p (eval e1 eval e2 : s)
ejp p (eval(e1 e2 ) : s)

Paso inductivo e = not e1 .


I.H: ps(ejp (comp e1 +
+ p) s = ejp p (eval e1 : s))
Queremos demostrar que:
ps(ejp (comp(not e1 ) ++ p) s = ejp p (eval(not e1 ) : s))
ejp (comp(not e1 ) +
+ p) s =
=Asoc ++
=I.H
=
=
=
=

ejp ((comp e1 ++[]) ++ p) s


ejp ((comp e1 ++([] ++ p)) s
ejp ([] ++ p) (eval e1 : s)
ejp ( : p) (eval e1 : s)
ejp p (ej [] (eval e1 : s))
ejp p ((eval e1 ) : s)
ejp p (eval(not e1 ) : s)

A continuaci
on damos una idea de la formalizacion de esta prueba en el sistema de deducci
on
natural.
11

6.3.

B
osquejo de la prueba formal (dentro del sistema de deducci
on natural)

Queremos probar que ` eP (e) donde es un conjunto de premisas adecuado y P (e) es la


formula que formaliza la propiedad requerida.
La formula a probar es P (e) definida como
P (e) =def ps ejp (comp e ++ p) s = ejp p (eval e : s)

se define como la siguiente uni


on de conjuntos de formulas:
= {IP } F L E
donde
IP es el principio de inducci
on para expresiones para el caso de P :
IP

=def

P (n) P (true) P (false)


e1 e2 (P (e1) P (e2 ) P (e1 + e2 ))
e1 e2 (P (e1) P (e2 ) P (e1 e2 ))
e1 e2 (P (e1) P (e2 ) P (e1 < e2 ))
e(P (e) P (not e))
e(P (e) P (iszero e))
eP (e)

F consta de las cerraduras universales de las ecuaciones que definen a las funciones eval, ej, ejp, comp.
F = { n(eval n = n), . . . ,

e1 e2 eval(e1 + e2) = eval e1 + eval e2 , . . .
v1v2s ej < (v1 : v2 : s) = (v1 < v2) : s , . . .
..
.

e comp(iszero e) = comp e ++[iszero]
}
L consta de las propiedades requeridas de las operaciones de listas:
Concatenaci
on de lista unitaria: x`([x] ++ ` = x : `).
Asociatividad de la concatenacion:
xyz x ++(y ++ z) = (x ++ y) ++ z
E contiene los llamados axiomas de igualdad:
Reflexividad: x(x = x)
Simetra xy(x = y y = x)
Transitividad: xyz(x = y y = z x = z)

12

Sustituci
on (Leibniz): xy(x = y A(x) A(y)) donde A es una formula cualquiera3
Alternativamente en vez de usar estas formulas directamente para derivar nuevas formulas o
ecuaciones podemos utilizar la l
ogica ecuacional discutida antes, es decir, usar las siguientes
reglas:
`s=t
`s=t `t=r
(Ref l)
(Sim)
(T rn)
`t=t
`t=s
`s=r
` s = t ` A(s)
(Rewrite)
` A(t)
donde A es cualquier f
ormula.
A continuaci
on bosquejamos la prueba formal ` eP (e).
Para esto basta probar el antecedente del axioma de induccion IP y usar modus ponens.
Como dicho antecedente es una conjuncion basta probar cada parte por separado y usar la
regla (I).
Cada parte se prueba formalizando las pruebas informales, dado que el razonamiento ecuacional est
a permitido por las hip
otesis de E y por las propiedades de listas L . Como
ejemplo formalizemos el caso base para n
umeros naturales:
Base P.D. ` P (n), es decir, ` ps(ejp (comp n ++ p) s = ejp p (eval n : s)).
1.
2.
3.
4.
5.
6.
7.
8.

6.4.

`
`
`
`
`
`
`
`

ejp (comp n +
+ p) s = ejp (comp n ++ p) s
ejp (comp n +
+ p) s = ejp ([n] ++ p) s
ejp (comp n +
+ p) s = ejp (n : p) s
ejp (comp n +
+ p) s = ejp p (ej n s)
ejp (comp n +
+ p) s = ejp p (n : s)
ejp (comp n +
+ p) s = ejp p (eval n : s)

s ejp (comp n +
+ p) s = ejp p (eval n : s) 
ps ejp (comp n ++ p) s = ejp p (eval n : s)

(Ref l)
(Rewrite) 1 def. comp n
(Rewrite) 2 prop. de listas
(Rewrite) 3 def. ejp
(Rewrite) 4 def. ej
(Rewrite) 5 def. eval
(I) 6, s
/ F V ()
(I) 7, p
/ F V ()

Para qu
e una prueba formal?

Una prueba formal como la que acabamos de bosquejar no es una argumentacion en alg
un
lenguaje natural, como el espa
nol, o bien semiformal como la mezcla de espa
nol y matematicas,
la cual es susceptible de errores dficiles de encontrar en casos de aplicacion real. Por ejemplo la
construccion de un compilador correcto (altamente confiable) de un lenguaje real como C (ver
http://compcert.inria.fr). Las pruebas formales constan de un proceso de calculo preciso que
sigue reglas bien definidas, en nuestro caso las reglas de deduccion natural. Una ventaja de construir
esta clase de pruebas es que debido a su naturaleza precisa son rigurosas, libres de ambig
uedades
y susceptibles de construirse y verificarse mecanicamente por programas llamados asistentes de
prueba como Coq (ver http://coq.inria.fr). Esta verificacion a la vez produce una certificaci
on
que garantiza que ciertas propiedades se cumplen, como por ejemplo la correctud de un compilador.
3

Basta con agregar la instancia de esta f


ormula para las f
ormulas A que necesitemos

13

Esto es deseable en sistemas cuyo funcionamiento incorrecto causa errores graves como sistemas de
radiacion para enfermos de cancer y sistemas de navegacion de vuelo.
El uso de sistemas l
ogicos para desarrollar aplicaciones con propiedades certificadas mediante prueba
formales ha generado una nueva
area dentro de las ciencias de la computacion conocida como
Metodos Formales.

14

Vous aimerez peut-être aussi