Upload
others
View
9
Download
0
Embed Size (px)
Citation preview
Enrique Martín MartínTesis Doctoral
Directores: Francisco J. López Fraguas
Juan Rodríguez Hortalá
Departamento de Sistemas Informáticos y ComputaciónUniversidad Complutense de Madrid
6 de julio de 2012
Sistemas de tipos en programación lógico-funcional
Contexto de la tesis
Programación lógico-funcional: integración de los dos principales paradigmas de programación declarativa.
Sistemas: Curry (PAKCS, Münster, KICS), Toy.
Programación lógica
Búsqueda indeterminista Variables lógicas
PROGRAMACIÓN LÓGICO-FUNCIONAL
Programación funcional
Funciones de orden superior Polimorfismo Damas-Milner Evaluación perezosa
Ejemplo de programa Toy
data nat = zero | succ nat
coin :: nat dup :: A -> (A,A)coin = zero dup X = (X,X)coin = succ zero
last :: [A] -> Alast Xs = if (Xs == Zs ++ [E]) then E
f :: ([A] -> A) -> boolf last = true
Ejemplo de programa Toy
data nat = zero | succ nat
coin :: nat dup :: A -> (A,A)coin = zero dup X = (X,X)coin = succ zero
last :: [A] -> Alast Xs = if (Xs == Zs ++ [E]) then E
f :: ([A] -> A) -> boolf last = trueFunciones indeterministas
Toy> coin == R { R -> zero }sol.1, more solutions (y/n/d/a) [y]? y { R -> (succ zero) } sol.2, more solutions (y/n/d/a) [y]? y no
Ejemplo de programa Toy
data nat = zero | succ nat
coin :: nat dup :: A -> (A,A)coin = zero dup X = (X,X)coin = succ zero
last :: [A] -> Alast Xs = if (Xs == Zs ++ [E]) then E
f :: ([A] -> A) -> boolf last = true
call-time choicelas copias de expresiones indeterministasrealizadas durante el paso de parámetros
comparten el mismo valor
Toy> dup coin == R { R -> (zero, zero) } sol.1, more solutions (y/n/d/a) [y]? y { R -> ((succ zero), (succ zero)) } sol.2, more solutions (y/n/d/a) [y]? y no
Ejemplo de programa Toy
data nat = zero | succ nat
coin :: nat dup :: A -> (A,A)coin = zero dup X = (X,X)coin = succ zero
last :: [A] -> Alast Xs = if (Xs == Zs ++ [E]) then E
f :: ([A] -> A) -> boolf last = true
Variables extras en las reglas(variables que solo aparecen en
el lado derecho)
Toy> last [] == R noToy> last [true, false] == R { R -> false }
Ejemplo de programa Toy
data nat = zero | succ nat
coin :: nat dup :: A -> (A,A)coin = zero dup X = (X,X)coin = succ zero
last :: [A] -> Alast Xs = if (Xs == Zs ++ [E]) then E
f :: ([A] -> A) -> boolf last = true
Patrones de orden superior(last tiene aridad 1)
Toy> f last == R { R -> true } Toy> f head == R no
Aplicaciones parciales deconstructoras o símbolos de función.
Al igual que las constructorascompletamente aplicadas, son valores.
Pueden aparecer en los ladosizquierdos de las reglas.
Permiten distinguir de maneraintensional distintas descripcionesde una misma función extensional.
Contexto de la tesis
Los lenguajes lógico-funcionales heredan directamente el sistema de tipos de Damas-Milner (DM) utilizado en programación funcional: Haskell, ML.
Ventajas: tipos principales, algoritmo de inferencia eficente.
PROBLEMAS de Damas-Milner
NO considera patrones de orden superior.
NO considera variables libres(estrechamiento).
Objetivo principal
Proponer sistemas de tipos para los lenguajeslógico-funcionales que manejen adecuadamentesus características (patrones de orden superior,
variables libres, etc.), evitando así los problemas queaparecen utilizando una adaptación directa de DM.
Objetivo I
Manejar adecuadamente los patrones de orden superior
Este programa está bien tipado utilizando Damas-Milner.
Sin embargo no preserva tipos:
not (cast zero) tiene tipo bool, ya que cast zero puede tener cualquier tipo.
Sin embargo, not zero no admite ningún tipo.
snd :: A -> B -> B unpack :: (A -> A) -> Bsnd X Y = Y unpack (snd X) = X
cast :: A -> B not :: bool -> boolcast X = unpack (snd X) not true = false
not false = true
Objetivo II
Conseguir un sistema de tipos para PLF más relajado, que siga garantizando la preservación de tipos.
Este programa está mal tipado utilizando Damas-Milner, sin embargo no viola la preservación de tipos.
Un sistema de tipos que aceptase esta función tendría interesantes posibilidades para la programación genérica.
size :: A -> natsize true = succ zerosize false = succ zerosize zero = succ zerosize (succ X) = succ (size X)size [] = succ zerosize (X:Xs) = succ (add (size X) (size Xs))
Objetivo III
Manejar adecuadamente el problema de la descomposición opaca
Los sistemas de PLF utilizan una igualdad estructural (==) predefinida de tipo A -> A -> bool que no podría definirse mediante reglas ya que estas estarían mal tipadas.
En presencia de patrones de orden superior, la igualdad estructural puede generar pasos de descomposición que no preservan los tipos:
(snd true) == (snd zero) está bien tipada.
Sin embargo, true == zero no admite ningún tipo.
snd :: A -> B -> Bsnd X Y = Y
Objetivo IV
Manejar las variables libres y extras, garantizando la preservación de tipos con estrechamiento
Las ligaduras generadas al evaluar (utilizando estrechamiento) pueden generar problemas de tipos de manera muy sencilla:
succ (F zero) tienen tipo nat cuando F tiene tipo nat -> nat, sin embargo, succ false no admite ningún tipo.
[f (snd X), X] tiene tipo [bool] cuando X tiene tipo bool, sin embargo, [true, zero] no admite ningún tipo.
and :: bool -> bool -> bool f :: (A -> A) -> booland true X = X f (snd zero) = trueand false X = false
Organización
1.Sistema de tipos con manejo seguro de patrones de orden superior
2.Sistema de tipos liberal
3.Aplicación del sistema de tipos liberal a la traducción de clases de tipos en PLF
4.Sistema de tipos con soporte para variables libres/extra y estrechamiento
5.Conclusiones
1.Sistema de tipos con manejo seguro de patrones de orden superior
2.Sistema de tipos liberal
3.Aplicación del sistema de tipos liberal a la traducción de clases de tipos en PLF
4.Sistema de tipos con soporte para variables libres/extra y estrechamiento
5.Conclusiones
Patrones de orden superior
¿Por qué causan problemas de tipos? Porque, a diferencia de los patrones de primer orden (aplicaciones
totales de símbolos de constructora), el tipo del patrón completo puede no determinar unívocamente el tipo de sus componentes.
Por ejemplo, saber que (snd X) tiene tipo A->A no nos indica el tipo de X, que podría ser cualquiera: bool, nat, [bool -> nat]...
Una adaptación directa de DM trata esta “opacidad ” comopolimorfismo, y es por ello que infiere el tipo (A->A)->Bpara la función unpack (donde B es el tipo de X desconocido).
snd :: A -> B -> B unpack :: (A -> A) -> Bsnd X Y = Y unpack (snd X) = X
Patrones de orden superior
¿Cómo solucionarlo?
a) Hacer una distinción entre variables transparentes y opacas de un patrón:
Una variable de datos X es opaca en un patrón t si su tipo no está unívocamente determinado por el tipo del patrón.
Si el tipo de X sí está unívocamente determinado por el tipo de t, dicha variable de datos es transparente.
b) Se prohíbe la aparición de variables críticas, esto es, variables opacas en los lados derechos de las reglas y en el cuerpo de λ-abstracciones y let-expresiones.
Ejemplo: La variable X es opaca en el patrón (snd X) y por tantocrítica en la regla unpack (snd X) = X, que sería rechazada.
Formalización del sistema de tipos
Hemos divido la tarea de derivar tipo para una expresión en dos:
a)Derivación de tipos básicaEs similar a Damas-Milner pero considerando la aparición de patrones compuestos en λ-abstracciones y let-expresiones (y distintos grados de polimorfismo en let-expresiones)
b)Derivación de tipos extendidaUtiliza la derivación anterior y comprueba que no aparecen variables críticas
Derivación de tipos básica
Derivación de tipos básica
Iguales que Damas-Milner
Derivación de tipos básica
Inventa suposiciones para las variables del patrón t y deriva su tipo.
Utiliza esas mismas suposiciones para derivar el tipo de e.
Derivación de tipos básica
Inventa suposiciones para las variables del patrón t y deriva su tipo
Debe derivar el mismo tipo para la expresión ligada.
Usa esas suposiciones para derivar el tipo de e
2.
Soportamos 2 tipos más de polimorfismo en let-expresiones
Derivación de tipos extendida
Una variable es opaca en un patrón si
X es opaca en snd X:
X no es opaca en snd [true,X]:
Una variable es crítica si es opaca en el patrón de una let-expresión o λ-abstracción y aparece en el resto de la expresión.
Derivación de tipos extendida
Una variable es opaca en un patrón si
X es opaca en snd X:
X no es opaca en snd [true,X]:
Una variable es crítica si es opaca en el patrón de una let-expresión o λ-abstracción y aparece en el resto de la expresión.
Variables críticas de una expresión
Inferencia de tipos
Siguiendo las mismas ideas que la inferencia Damas-Milner: usar variables frescas y unificación.
Corrección:
Completitud : Si entonces tal que
Maximalidad : Si y entonces tal que
Preservación de tipos
Solo se garantiza para programas bien tipados.
Un programa está bien tipado si cada regla cumple:
Utiliza la semántica de let-reescritura [López-Fraguas et al.,2008]. Por tanto no considera estrechamiento ni variables libres/extra.
Preservación de tipos
Ejemplo: casting polimórfico
snd :: A -> B -> B unpack :: (A -> A) -> Bsnd X Y = Y unpack (snd X) = X
cast :: A -> B not :: bool -> boolcast X = unpack (snd X) not true = false
not false = true X es una variable opacaen el patrón snd X
X es crítica porqueaparece en el ladoderecho de la regla
Por tanto, la regla de unpack está mal tipada
1.Sistema de tipos con manejo seguro de patrones de orden superior
2.Sistema de tipos liberal
3.Aplicación del sistema de tipos liberal a la traducción de clases de tipos en PLF
4.Sistema de tipos con soporte para variables libres/extra y estrechamiento
5.Conclusiones
Motivación del sistema liberal
El sistema de tipos anterior ofrece algunas posibilidades limitadas para la programación genérica:
(nótese que no hay variables críticas, pues X está forzado a tener tipo nat)
La función code recibe argumentos de diferentes tipos encapsulados en un patrón opaco, que son inspeccionados
Sin embargo, no produce ningún error de tipos durante la ejecución
data bit = i | o data cont where cont :: A -> cont
code :: cont -> [bit] code (cont true) = [o,o,o] code (cont false) = [o,o,i]code (cont zero) = [o,i,o] code (cont (succ X)) = [o,i,i] ++ code (cont X)
Motivación del sistema liberal
¿Se podría ampliar la liberalidad sin perder la preservación de tipos?
Este programa es similar al anterior pero sería rechazado porque los tipos de sus reglas son incompatibles:
size :: bool -> nat
size :: nat -> nat
size :: [A] -> nat
Sin embargo, sigue sin producir errores de tipos.
size :: A -> nat
size true = succ zero size false = succ zerosize zero = succ zero size (succ X) = succ (size X)size [] = succ zero size (X:Xs) = succ (add (size X) (size Xs))
Motivación del sistema liberal
¿Se podría ampliar la liberalidad sin perder la preservación de tipos?
Este programa es similar al anterior pero sería rechazado porque los tipos de sus reglas son incompatibles:
size :: bool -> nat
size :: nat -> nat
size :: [A] -> nat
Sin embargo, sigue sin producir errores de tipos.
size :: A -> nat
size true = succ zero size false = succ zerosize zero = succ zero size (succ X) = succ (size X)size [] = succ zero size (X:Xs) = succ (add (size X) (size Xs))
Motivación del sistema liberal
¿Se podría ampliar la liberalidad sin perder la preservación de tipos?
Este programa es similar al anterior pero sería rechazado porque los tipos de sus reglas son incompatibles:
size :: bool -> nat
size :: nat -> nat
size :: [A] -> nat
Sin embargo, sigue sin producir errores de tipos.
size :: A -> nat
size true = succ zero size false = succ zerosize zero = succ zero size (succ X) = succ (size X)size [] = succ zero size (X:Xs) = succ (add (size X) (size Xs))
Motivación del sistema liberal
¿Se podría ampliar la liberalidad sin perder la preservación de tipos?
Este programa es similar al anterior pero sería rechazado porque los tipos de sus reglas son incompatibles:
size :: bool -> nat
size :: nat -> nat
size :: [A] -> nat
Sin embargo, sigue sin producir errores de tipos.
size :: A -> nat
size true = succ zero size false = succ zerosize zero = succ zero size (succ X) = succ (size X)size [] = succ zero size (X:Xs) = succ (add (size X) (size Xs))
Motivación del sistema liberal
¿Se podría ampliar la liberalidad sin perder la preservación de tipos?
Este programa es similar al anterior pero sería rechazado porque los tipos de sus reglas son incompatibles:
size :: bool -> nat
size :: nat -> nat
size :: [A] -> nat
Sin embargo, sigue sin producir errores de tipos.
size :: A -> nat
size true = succ zero size false = succ zerosize zero = succ zero size (succ X) = succ (size X)size [] = succ zero size (X:Xs) = succ (add (size X) (size Xs))
Objetivos del sistema liberal
Desarrollar un sistema de tipos para PLF con el grado más alto de liberalidad posible que siga garantizando la preservación de tipos.
Como semántica consideraremos la let-reescritura, por tanto el estrechamiento y las variables libres/extra no estarán permitidas.
Noción de programa bien tipado
Muy sencilla: Basada en la derivación básica presentada anteriormente
Requiere la declaración de tipos de todas las constructoras y símbolos de función
Regla a regla, sin importar el orden
Una regla de programa está bien tipada si:
a) admiten tipo
b) El tipo más general de e y sus variables es más general que aquellos para el lado izquierdo
Intuición: una regla está bien tipada si el lado derecho no fuerza los tipos más que
el lado izquierdo
Ejemplo: size
size :: A -> natsize true = succ zero size false = succ zerosize zero = succ zero size (succ X) = succ (size X)size [] = succ zero size (X:Xs) = succ (add (size X) (size Xs))
Ejemplo: size
size :: A -> natsize true = succ zero size false = succ zerosize zero = succ zero size (succ X) = succ (size X)size [] = succ zero size (X:Xs) = succ (add (size X) (size Xs))
size true :: nat succ zero :: nat
Ejemplo: size
size :: A -> natsize true = succ zero size false = succ zerosize zero = succ zero size (succ X) = succ (size X)size [] = succ zero size (X:Xs) = succ (add (size X) (size Xs))
size (succ X) :: natX :: nat
succ (size X) :: natX :: A
(nat, A) es más general que (nat, nat)
Ejemplo: size
size :: A -> natsize true = succ zero size false = succ zerosize zero = succ zero size (succ X) = succ (size X)size [] = succ zero size (X:Xs) = succ (add (size X) (size Xs))
size (X:Xs) :: natX :: A
Xs :: [A]
succ (add (size X) (size Xs)) :: natX :: BXs :: C
(nat, B, C) es más general que (nat, A, [A])
Ejemplo: casting polimórfico
snd :: A -> B -> B unpack :: (A -> A) -> Bsnd X Y = Y unpack (snd X) = X
cast :: A -> B not :: bool -> boolcast X = unpack (snd X) not true = false
not false = true
Ejemplo: casting polimórfico
snd :: A -> B -> B unpack :: (A -> A) -> Bsnd X Y = Y unpack (snd X) = X
cast :: A -> B not :: bool -> boolcast X = unpack (snd X) not true = false
not false = trueunpack (snd X) :: BX :: A
X :: C
Mal tipada porque (C,C) no es más general que (B,A)
Propiedades del sistema liberal
Preservación de tipos:
Propiedades del sistema liberal
Máxima liberalidad:Si en una regla de programa el lado derecho fuerza los tipos más que el izquierdo entonces:
Si una regla no está bien tipada sepuede construir una derivación que
rompe la preservación de tipos
Propiedades del sistema liberal
Máxima liberalidad:Si en una regla de programa el lado derecho fuerza los tipos más que el izquierdo entonces:
Equivalencia con reglas que preservan tipos:
Propiedades del sistema liberal
Máxima liberalidad:Si en una regla de programa el lado derecho fuerza los tipos más que el izquierdo entonces:
Equivalencia con reglas que preservan tipos:
Para cualquier tipo existe un patrón queúnicamente puede tener dicho tipo.
Al aplicar la regla con cualquier instancia desus argumentos se preserva el tipo.
Posibilidades del sistema liberal
Manejo adecuado de la opacidad generada por los patrones de orden superior
snd :: A -> B -> B unpack :: (A -> A) -> Bsnd X Y = Y unpack (snd X) = X
cast :: A -> B not :: bool -> boolcast X = unpack (snd X) not true = false
not false = trueunpack (snd X) :: BX :: A
X :: C
Mal tipada porque (C,C) no es más general que (B,A)
Posibilidades del sistema liberal
Soporte para constructoras existenciales
data key where mkKey :: A -> (A -> nat) -> key
getKey :: key -> natgetKey (mkKey X F) = F X
getKey (mkKey X F) :: natF :: A -> nat
X :: A
F X :: CF :: B -> C
X :: B
Bien tipada porque (C, B -> C, B) es más general que (nat, A -> nat, A)
Posibilidades del sistema liberal
Soporte para funciones indexadas por tipo (funciones con un comportamiento diferente para cada tipo)
eq :: A -> A -> booleq true true = true eq zero zero = trueeq true false = false eq zero (succ Y) = falseeq false true = false eq (succ X) zero = falseeq false false = true eq (succ X) (succ Y) = eq X Y
eq (X1,Y1) (X2,Y2) = (eq X1 X2) /\ (eq Y1 Y2)eq (snd X) (snd Y) = eq X Y
De esta manera se puede definir unaigualdad estructural mediante reglas, evitando
los problemas de descomposición opaca
Posibilidades del sistema liberal
Soporte para la funciones genéricas(funciones que sirven para todos los tipos con la misma definición)
data univ = c nat [univ]
usize :: univ -> natusize (c N L) = succ (sum (map usize L))
toU :: A -> univtoU true = c zero [] toU false = c (succ zero) []toU zero = c (succ2 zero) [] toU (succ X) = c (succ3 zero) [toU X]toU [] = c (succ4 zero) [] toU (X:Xs) = c (succ5 zero) [toU X, toU Xs]
size :: A -> natsize = usize . toU
Consideraciones
Se necesita declarar los tipos de las funciones para comprobar que un programa está bien tipado.
Se pierde la parametricidad en el sentido de Reynolds, ya que las reglas pueden inspeccionar argumentos polimórficos(Sin embargo la parametricidad no es aplicable PLF por más motivos: indeterminismo, variables extra o estrechamiento)
Se consideran como bien tipadas expresiones para las que no tenemos ninguna regla aplicable. Ejemplos: eq [ ] [ ], size [ ]... (no tan diferente de head [ ]).
1.Sistema de tipos con manejo seguro de patrones de orden superior
2.Sistema de tipos liberal
3.Aplicación del sistema de tipos liberal a la traducción de clases de tipos en PLF
4.Sistema de tipos con soporte para variables libres/extra y estrechamiento
5.Conclusiones
Motivación de la nueva traducción
Las clases de tipos proporcionan una manera modular y limpia de escribir funciones sobrecargadas
Tradicionalmente se implementan mediante una traducción que introduce diccionarios
Sin embargo, en PLF los diccionarios no interaccionan adecuadamente con el indeterminismo y la semántica de call-time choice, produciendo respuestas perdidas
Utilizando el sistema de tipos liberal, es posible una implementación alternativa de las clases de tipos en PLF que soluciona dicho problema a la vez que genera programas más rápido y compactos
Ejemplo problemático
class arb A where arb :: A instance arb bool where arb = true arb = false arbL2 :: arb A => [A]arbL2 = [arb, arb]
Cada declaración de clasegenera una declaración de datos definiendo el
diccionario, además de funciones proyectoras
Ejemplo problemático
class arb A where arb :: A instance arb bool where arb = true arb = false arbL2 :: arb A => [A]arbL2 = [arb, arb]
data dictArb A = dictArb A
arb :: dictArb A -> Aarb (dictArb F) = F
Ejemplo problemático
class arb A where arb :: A instance arb bool where arb = true arb = false arbL2 :: arb A => [A]arbL2 = [arb, arb]
data dictArb A = dictArb A
arb :: dictArb A -> Aarb (dictArb F) = F
arbbool
:: bool
arbbool
= true
arbbool
= false
dictArbBool :: dictArb bool dictArbBool = dictArb arb
bool
Cada declaración deinstancia genera la definiciónde un diccionario concreto
Ejemplo problemático
class arb A where arb :: A instance arb bool where arb = true arb = false arbL2 :: arb A => [A]arbL2 = [arb, arb]
data dictArb A = dictArb A
arb :: dictArb A -> Aarb (dictArb F) = F
arbbool
:: bool
arbbool
= true
arbbool
= false
dictArbBool :: dictArb bool dictArbBool = dictArb arb
bool
arbL2 :: dictArb A -> [A]arbL2 DA = [arb DA, arb DA]
Las funcionessobrecargadas son extendidas
para aceptar diccionarioscomo argumentos
Ejemplo problemático
data dictArb A = dictArb A
arb :: dictArb A -> Aarb (dictArb F) = F
arbbool
:: bool
arbbool
= true
arbbool
= false
dictArbBool :: dictArb bool dictArbBool = dictArb arb
bool
arbL2 :: dictArb A -> [A]arbL2 DA = [arb DA, arb DA]
Se pierden respuestas esperadas:
> arbL2::[bool]
De manera similar se genera el valor [false,false]
Sin embargo, los valores [true,false] y [false,true]
no se pueden alcanzar
Traducción alternativa: intuición
Pasar testigos de tipos (patrones que representan los distintos tipos) en lugar de diccionarios.(Enfoque propuesto en [Thatté,94])
Las funciones sobrecargadas son traducidas a funciones indexadas por tipo.
Estas utilizan el testigo pasado como argumento para decidir el comportamiento esperado.
Cada regla de una instancia genera una regla de la función indexada por tipo.
El programa traducido está bien tipado en el sistema liberal.
Testigos de tipos
Una manera de representar tipos como valores
Extender cada tipo de datos con una nueva constructora
Ejemplos: data nat = z | s nat | #nat data bool = true | false | #bool data [A] = nil | cons A (list A) | #list A
Los testigos de tipo tienen el mismo tipo que representan
#list #bool :: [bool]
#list (#list #nat) :: [[nat]]
Decoraciones
La traducción utiliza las decoraciones de tipos en los símbolos de función
Estas decoraciones son introducidas por una fase de comprobación de tipos previa utilizando el sistema de tipos usual de clase de tipos
g X = eq X [true]
g::[bool]->bool X = eq::<eq [bool]> => [bool]->[bool]->bool X [true]
Traducción: clases
class arb A where arb :: A instance arb bool where arb = true arb = false arbL2 :: arb A => [A]arbL2::<arb A> => [A] = [arb::<arb A> => A, arb::<arb A> => A]
Cada función miembro declarada en una clase de tiposgenera una función indexada por tipo que
acepta un testigo de tipo
arb :: A -> A
Traducción: instancias
Cada regla de una función miembro generauna regla de la función indexada por tipoque acepta el testigo de tipo adecuado
class arb A where arb :: A instance arb bool where arb = true arb = false arbL2 :: arb A => [A]arbL2::<arb A> => [A] = [arb::<arb A> => A, arb::<arb A> => A]
arb :: A -> A
arb #bool = truearb #bool = false
Traducción: funciones
class arb A where arb :: A instance arb bool where arb = true arb = false arbL2 :: arb A => [A]arbL2::<arb A> => [A] = [arb::<arb A> => A, arb::<arb A> => A]
Se pasan los testigos de tipos adecuados a lasfunciones sobrecargadas
arb :: A -> A
arb #bool = truearb #bool = false
arbL2 :: A -> [A]arbL2 X
A =
[arb XA, arb X
A]
Ventajas de la nueva traducción
arb :: A -> A
arb #bool = truearb #bool = false
arbL2 :: A -> [A]arbL2 X
A =
[arb XA, arb X
A]
Se recuperan las respuestas perdidas:
> arbL2::<eq bool> => [bool]
De manera similar se genera el valor [false,true]
A diferencia de los diccionarios (que contienenfunciones), la compartición de testigos de tipos
no es problemática porque son valores.
Ventajas de la nueva traducción
Programa Ganancia
eqlist 1.6
fib 2.3
galeprimes 1.5
memberord 2.3
mergesort 1
permutsort 1.7
quicksort 1
Mejora en el el tiempo de ejecución de los programas traducidos con respecto a los programas generados por la traducción clásica de clases de tipos.
Tests: fragmentos de programas reales que usan las clases clases de tipos eq, ord y num.
Ganancia media obtenida en el sistema Toy evaluando 100 expresiones aleatorias.
1.Sistema de tipos con manejo seguro de patrones de orden superior
2.Sistema de tipos liberal
3.Aplicación del sistema de tipos liberal a la traducción de clases de tipos en PLF
4.Sistema de tipos con soporte para variables libres/extra y estrechamiento
5.Conclusiones
Motivación
Los pasos de estrechamiento no preservan los tipos.
La sustitución unifica la expresión and true Y y el lado izquierdo de la regla and true X = X (aunque no es un unificador más general).
Sin embargo, el paso no preserva tipos
and true Y :: bool
zero :: nat
and :: bool -> bool -> bool f :: (A -> A) -> booland true X = X f (snd zero) = trueand false X = false
Motivación
Los pasos de estrechamiento no preservan los tipos.
La sustitución unifica la expresión and true Y y el lado izquierdo de la regla and true X = X (aunque no es un unificador más general).
Sin embargo, el paso no preserva tipos
and true Y :: bool
zero :: nat
and :: bool -> bool -> bool f :: (A -> A) -> booland true X = X f (snd zero) = trueand false X = false
¿El problema es queno son unificadores
más generales?
Motivación
Los pasos de estrechamiento utilizando unificadores más generales tampoco preservan los tipos.
La sustitución es un unificador más general de la expresión f (snd U) y el lado izquierdo de la regla de f.
Sin embargo, el paso no preserva tipos
(f (snd U),not U)::(bool,bool)
(true, not zero) está mal tipado
and :: bool -> bool -> bool f :: (A -> A) -> booland true X = X f (snd zero) = trueand false X = false
Motivación
Los pasos de estrechamiento utilizando unificadores más generales tampoco preservan los tipos.
La sustitución es un unificador más general de la expresión f (snd U) y el lado izquierdo de la regla de f.
Sin embargo, el paso no preserva tipos
(f (snd U),not U)::(bool,bool)
(true, not zero) está mal tipado
and :: bool -> bool -> bool f :: (A -> A) -> booland true X = X f (snd zero) = trueand false X = false
¿El problema son lospatrones de orden
superior?
Motivación
Las variables de orden superior también generan problemas para garantizar la preservación de tipos.
La sustitución es un unificador más general de la expresión F zero y el lado izquierdo de la regla de and false X = false.
Sin embargo, el paso no preserva tipos
succ (F zero) :: nat
succ false está mal tipado
and :: bool -> bool -> bool f :: (A -> A) -> booland true X = X f (snd zero) = trueand false X = false
Motivación
Es necesario estudiar bajo qué condiciones los pasos de estrechamiento generales
preservan los tipos
Clave de la pérdida de preservación de tipos
En todos los ejemplos las sustituciones utilizadas son sustituciones de estrechamiento válidas.
Sin embargo, son sustituciones mal tipadas. Esto es, sustituyen variables por patrones de otro tipo:
Las variables booleanas X e Y son sustituidas por zero.
La variable booleana U es reemplazada por zero.
La variable de orden superior F de tipo nat->nat es sustituida por and false, de tipo bool->bool. Además la variable booleana X es sustituida por zero.
Condición general
Si los pasos de estrechamiento usansustituciones bien tipadas, la
preservación de tipos está garantizada
Estrechamiento bien tipado
Sistema de tipos similar a Damas-Milner pero extendido para soportar variables extra en las reglas (λ-abstracciones)
La regla está bien tipada si el tipo de laλ-abstracción es una variante del tipo de f
Un programa está bien tipado – – si todas sus reglaslo están
Añadimos también suposiciones sobre laslas variables extra que solo aparecen en el
cuerpo de la λ-abstracción
Un paso de let-estrechamiento [López-Fraguas et al.,2008] es un paso de estrechamiento bien tipado ( ) si la sustitución θ es una sustitución bien tipada
Aspectos técnicos: como los pasos de estrechamiento pueden introducirnuevas variables, la noción de sustitución bien tipada y preservación de tiposdeben considerar suposiciones adecuadas para esas nuevas variables. Esas suposiciones están asociadas al paso de estrechamiento realizado.
Estrechamiento bien tipado
Problema operacional
Comprobar que las sustituciones están bien tipadas requiere comprobaciones en tiempo de ejecución en cada paso de estrechamiento.
¿Es posible encontrar una relación de estrechamiento más pequeña que evite dichas comprobaciones?
Sí, imponiendo restricciones sobre el programa y los pasos de estrechamiento
Estrechamiento reducido
Las sustituciones deben ser unificadores más generales Así solucionamos el problema en
Evitar los pasos que ligan variables de orden superior (comportamiento similar a la residuación)
Así solucionamos el problema en
Evitar patrones opacos en los lados izquierdos de las reglas Así solucionamos el problema en
and :: bool -> bool -> bool f :: (A -> A) -> booland true X = X f (snd zero) = trueand false X = false
Estrechamiento reducido
Las sustituciones deben ser unificadores más generales Así solucionamos el problema en
Evitar los pasos que ligan variables de orden superior (comportamiento similar a la residuación)
Así solucionamos el problema en
Evitar patrones opacos en los lados izquierdos de las reglas Así solucionamos el problema en
and :: bool -> bool -> bool f :: (A -> A) -> booland true X = X f (snd zero) = trueand false X = false
Patrón opaco
Estrechamiento reducido
Un paso de let-estrechamiento es un paso de estrechamiento reducido ( ) si:
No liga variables de orden superior
Utiliza un unificador más general
Los patrones en los lados izquierdos de las reglas son transparentes
Los pasos de estrechamiento reducido no necesitan comprobaciones en tiempo de ejecución
Los pasos de estrechamiento reducidoutilizando programas bien tipados
preservan los tipos
Estrechamiento necesario
Utilizando la preservación de tipos del estrechamiento reducido, es posible demostrar la preservación de tipos en un lenguaje Curry simplificado que utilice estrechamiento necesario [Antoy et al.,2000]
Lenguaje Curry simplificado: Patrones de primer orden → patrones transparentes
Residuación no liga → variables de orden superior
Enfoque transformacional: los pasos de estrechamiento necesarios son simulados por pasos de estrechamiento reducido (que preserva tipos) sobre un programa transformado.
Estrechamiento necesario
Idea de la demostración:
Ambas transformaciones generan programas bien tipados.
Las reducciones de estrechamiento necesario sobre el programa original P son simuladas con reducciones de estrechamiento reducido sobre el programa transformado en formato uniforme P''. Por lo tanto preservan los tipos.
OISP P' Formatouniforme
P''
[Antoy,2001] [Zartmann,1997]
1.Sistema de tipos con manejo seguro de patrones de orden superior
2.Sistema de tipos liberal
3.Aplicación del sistema de tipos liberal a la traducción de clases de tipos en PLF
4.Sistema de tipos con soporte para variables libres/extra y estrechamiento
5.Conclusiones
Conclusiones
1. Manejo adecuado de los patrones de orden superior
Publicaciones: LNCS con artículos revisados y seleccionados de WFLP'09, Information & Computation (2013)
Definición de las variables opacas en un patrón (aquellas cuyo tipo no está completamente determinado por el tipo del patrón)
Impedir la aparición de variable opacas en los cuerpos de let-expresiones y λ-abstracciones: variables críticas
Conclusiones
2. Desarrollo de un sistema de tipos relajado para PLF que garantiza la preservación de tipos
Publicaciones: APLAS '10, Mathematical Structures in Computer Science (2013)
El lado derecho de las reglas no debe restringir el tipo más que el lado izquierdo
Aplicaciones: soporta funciones indexadas por tipo, programación genérica, constructoras existenciales.
Ejemplo destacado: Traducción alternativa de clases de tipos (PEPM '11)
Es lo más relajado posible garantizando la preservación de tipos.
Conclusiones
3. Manejo adecuado del problema de la descomposición opaca
Al permitir funciones indexadas por tipo, la igualdad estructural se puede definir por reglas y no ser una primitiva ad-hoc
Las reglas que conducen a la descomposición opaca son consideradas mal tipadas, ya que no preservan el tipo
Conclusiones
4. Manejo adecuado de las variables libres y extras, garantizando la preservación de tipos con estrechamiento
Publicaciones: PEPM '12
Los pasos de estrechamiento con sustituciones bien tipadas preservan los tipos
El estrechamiento reducido preserva los tipos sin necesidad de comprobaciones en tiempo de ejecución
Aplicaciones: demostrar la preservación de tipos del estrechamiento necesario
Publicaciones Francisco J. López Fraguas, Enrique Martin-Martin, Juan Rodríguez-Hortalá
Safe Typing of Functional Logic Programs with Opaque Patterns and Local BindingsInformation and Computation, aparecerá en 2013
Francisco J. López Fraguas, Enrique Martin-Martin, Juan Rodríguez-HortaláA Liberal Type System for Functional Logic ProgramsMathematical Structures in Computer Science, aparecerá en 2013
Francisco J. López Fraguas, Enrique Martin-Martin, Juan Rodríguez-HortaláWell-typed Narrowing with Extra Variables in Functional-Logic ProgrammingACM SIGPLAN 2012 Workshop on Partial Evaluation and Program Manipulation (PEPM), 2012
Enrique Martin-MartinType Classes in Functional Logic ProgrammingACM SIGPLAN 2011 Workshop on Partial Evaluation and Program Manipulation (PEPM), 2011
Francisco J. López Fraguas, Enrique Martin-Martin, Juan Rodríguez-HortaláLiberal Typing for Functional Logic Programs 8th Asian Symposium on Programming Languages and Systems (APLAS), 2010
Francisco J. López Fraguas, Enrique Martin-Martin, Juan Rodríguez-HortaláNew Results on Type Systems for Functional Logic Programming18th International Workshop on Functional and (Constraint) Logic Programming –RevisedSelected Papers–, 2009
Sistemas
Rama de Toy 2.3.1 con patrones opacos seguroshttp://gpd.sip.ucm.es/Toy2SafeOpaquePatterns
Rama de Toy 2.3.1 con sistema de tipos liberalhttp://gpd.sip.ucm.es/Toy2Liberal
Interfaz web del sistema de tipos liberal (soporte de sintaxis GADT)http://gpd.sip.ucm.es/LiberalTyping
Trabajo futuro
Patrones opacos Aplicar un enfoque similar al de los tipos existenciales
[Läufer & Odersky, 1994] para tratar las variables opacas
No todas las variables críticas generan problemas. Relajar el sistema de tipos para permitir usos seguros de las variables críticas. Primeros avances realizados en (Information and Computation 2013)
Trabajo futuro
Sistema de tipos liberal Aunque en general no existen tipos principales, estudiar
situaciones donde algún tipo de inferencia es posible
Considerar la combinación del sistema de tipos liberal, clases de tipos y el sistema de tipos con manejo de variables opacas. Estudiar las propiedades del sistema resultante (preservación de tipos, tipos principales, etc.)
Trabajo futuro
Traducción alternativa de clases de tipos Implementar completamente la traducción en Toy para poder
comprobar la ganancia de velocidad con conjunto amplio de programas reales
Investigar si en la traducción encajan conocidas extensiones de las clases de tipo como clases multiparámetro o clases de constructoras
Trabajo futuro
Descomposición opaca Ampliar la expresividad del sistema de tipos para que igualdades
que provocan descomposición opaca sean consideradas mal tipadas. Requeriría ampliar la información de tipos para expresar los tipos de sus sub-expresiones (enviado a PPDP '12)
Trabajo futuro
Variables libres y estrechamiento Afinar el sistema de tipos para que el estrechamiento reducido
preserve tipos aún considerando patrones opacos en la reglas. Para ello parece ser conveniente recuperar la parametricidad del sistema de tipos, posiblemente utilizando un enfoque similar a los tipos existenciales.
¡Gracias!