PLP - Recuperatorio Primer Parcial - 1er cuatrimestre de 2012 Este examen se aprueba obteniendo al menos 65 puntos en total, y al menos 5 puntos por cada tema. Poner nombre, apellido y número de orden en cada hoja, y numerarlas. Se puede utilizar todo lo definido en las prácticas y todo lo que se dio en clase, colocando referencias claras. El puntaje de los distintos ı́tems no está necesariamente relacionado con su dificultad. Ejercicio 1 - Programación funcional (40 puntos) Durante este ejercicio no se puede usar recursión explı́cita a menos que se indique lo contrario. Para resolver un ı́tem pueden utilizarse las funciones definidas en los items anteriores, más allá de si fueron resueltos correctamente o no. También pueden usar todo lo definido en el Prelude y en el módulo List. En este ejercicio trabajaremos con fórmulas de la lógica proposicional de acuerdo con las siguientes definiciones: type VarProp = String data Prop = Var VarProp | Neg Prop | Or Prop Prop type Valuacion = VarProp->Bool Las variables proposicionales se representan con un nombre como, por ejemplo, "llueve" o "P". a) (10 puntos) Dar el tipo y definir la función foldP que implemente un esquema de recursión apropiado para el tipo Prop. En este ı́tem se puede usar recursión explı́cita. b) (5 puntos) Definir la función proposiciones::Prop->[VarProp] que computa la lista de variables proposicionales que aparecen en la fórmula dada. No debe contener repetidos. Sugerencia: Usar nub::Eq a => [a]->[a] que quita duplicados de una lista. c) (5 puntos) Definir la función evaluacion::Valuacion->Prop->Bool que computa el valor de verdad de una fórmula según una valuación. d) (10 puntos) Definir la función valuacionesRelevantes::[VarProp]->[Valuacion] que a partir de una lista de n variables proposicionales sin repetidos computa la lista de las 2n valuaciones que difieren en los valores de verdad que le asignan a dichas variables. Las valuaciones generadas asignarán True a las variables no listadas. e) (10 puntos) Definir la función equivalentes::Prop->Prop->Bool que computa si dos fórmulas son lógicamente equivalentes. Suponer que las variables proposicionales que aparecen en una fórmula son exactamente las mismas que ocurren como subtérminos en la otra. Sugerencia: Recordar que dos fórmulas de la lógica proposicional son lógicamente equivalentes sii para toda valuación relevante v, los valores de verdad que se obtienen al evaluar las fórmulas según v son iguales. El concepto de valuación relevante es el mismo que el del inciso anterior. De este modo, si n es el número de variables proposicionales que figuran en las fórmulas que cuya equivalencia se quiere analizar, se deben considerar sólo las 2n valuaciones que difieren en los valores que le asignan a aquellas variables. Usar las funciones definidas arriba proposiciones, evaluacion y valuacionesRelevantes, además de all::(a->Bool)->[a]->Bool, que retorna True sii todos los elementos de la lista satisfacen la condición dada. Por ejemplo, se obtiene True al evaluar all (<10) [1,3,5,7,9]. 1 Ejercicio 2 - Cálculo Lambda Tipado (30 puntos) En este ejercicio consideraremos el cálculo lambda tipado con listas: M ::= · · · | [ ]σ | M : N σ ::= · · · | [σ] Γ . [ ]σ : [σ] V ::= · · · | [ ]σ | V1 : V2 Γ . M : σ Γ . N : [σ] Γ . M : N : [σ] Extenderemos este cálculo para soportar multidiccionarios, los cuales son diccionarios que admiten varios valores para una misma clave. Formalmente, el conjunto de tipos y términos se modifica de la siguiente manera: ? σ ::= · · · | Dσ,τ M ::= · · · | N ilσ,τ | M [N ] ← O | valores(M, N ) | map(M, F ) ? El tipo Dσ,τ representa los multidiccionarios con claves de tipo σ y valores de tipo τ . La construcción será mediante el término N ilσ,τ para un multidiccionario vacı́o, y M [N ] ← O para agregar O con clave N al multidiccionario M . Utilizaremos la expresión valores(M, N ) que listará los valores definidos para la clave N en el multidiccionario M de manera tal que aparezcan con la misma multiplicidad en la lista que en el multidiccionario, sin importar el orden, y que para aquellas claves no definidas se retorne la lista vacı́a. ? mediante ? en un Dσ,ρ Adicionalmente, introducimos la función map(M, F ) que transforma M de un Dσ,τ una función F definifida como σ → τ → ρ (notar que esta función transforma los valores utilizando la clave y el valor para cada caso particular). Por ejemplo, si M = ((N ilBool,N at [true] ← 3)[f alse] ← 4)[true] ← 11 y F es una función que si la clave es f alse conserva la definición original y en caso contrario la cambia por 0, entonces la expresión map(M, F ) debe denotar el mismo valor que ((N ilBool,N at [true] ← 0)[f alse] ← 4)[true] ← 0. a) (10 puntos) Introducir las reglas de tipado para la extensión propuesta. b) (20 puntos) Definir el conjunto de valores e introducir las reglas de semántica para la extensión propuesta. Ejercicio 3 - Inferencia de tipos (30 puntos) Se desea extender el algoritmo de inferencia para soportar tablas con historia, las cuales ya fueron vistas en el primer parcial. Una tabla es una estructura de datos en la cual los valores se encuentran indexados mediante dos claves. Recordemos los conjuntos de tipos y términos: σ ::= · · · | Tablaρσ,τ M ::= · · · | Vacı́aσ,τ (M ) | M [N ][O] ← P | fold M base(def ) = N ; recursión(c1 , c2 , val, rec) = O Las reglas de tipado son las siguientes: Γ . M : Tablaρσ,τ Γ ∪ {def : ρ} . N : ψ Γ ∪ {c1 : σ, c2 : τ, val : ρ, rec : ψ} . O : ψ Γ . fold M base(def ) = N ; recursión(c1 , c2 , val, rec) = O : ψ Γ.M:ρ Γ . Vacı́aσ,τ (M ) : Tablaρσ,τ Γ . M : Tablaρσ,τ Γ . N : σ Γ . O: τ Γ . M [N ][O] ← P : Tablaρσ,τ Γ.P:ρ a) (20 puntos) Dar la extensión al algoritmo necesaria para soportar el tipado de la nueva estructura. Recordar que el parámetro de entrada es un término sin anotaciones de tipos. b) (10 puntos) Aplicar el algoritmo extendido para tipar la siguiente expresión: λx.fold Vacı́a(x) base(def ) = def ; recursión(c1 , c2 , val, rec) = if rec then c1 else c2 2