Paradigmas de Lenguajes de Programación 1er Cuatrimestre de 2014 Práctica No 3 - Inferencia de Tipos Aclaraciones: Los ejercicios marcados con el sı́mbolo F constituyen un subconjunto mı́nimo de ejercitación. Sin embargo, aconsejamos fuertemente hacer todos los ejercicios. Usaremos las expresiones de tipos y términos vistas en clase, con los tipos Bool, Nat y funciones ya definidos. Para esta práctica será necesario utilizar los axiomas y reglas de tipado e inferencia vistos en clase (tanto en las teóricas como en las prácticas). Siempre que se pide definir extensiones, se asume que el algoritmo de unificación (MGU) y el de borrado (Erase) ya se encuentran correctamente extendidos, de manera que sólo es necesario extender el algoritmo W (también conocido como Principal Typing). Ejercicio 1 Unir con flechas los tipos que unifican entre sı́ (entre una fila y la otra). Para cada par unificable, exhibir el mgu (“most general unifier”). t→u t u → Bool Nat a→b→c Nat → Bool (Nat → u) → Bool Nat → u → Bool Ejercicio 2 Decidir, utilizando el método del árbol, cuáles de las siguientes expresiones son tipables. Mostrar qué reglas y sustituciones se aplican en cada paso y justificar por qué no son tipables aquéllas que fallan. i. λz. if z then 0 else succ(0) v. if True then (λx. 0) 0 else (λx. 0) False ii. λy. succ((λx.x) y) vi. (λf. if True then f 0 else f False) (λx. 0) iii. λx. if isZero(x) then x else (if x then x else x) iv. λx.λy. if x then y else succ(0) vii. λx.λy.λz. if z then y else succ(x) viii. fix (λx. pred(x)) Para el punto viii, asumir extentido el algoritmo de inferencia con W(f ix) = ∅ . f ixa : (a → a) → a donde a es una variable fresca. Ejercicio 3 F Utilizando el árbol de inferencia, inferir el tipo de las siguientes expresiones o demostrar que no son tipables. En cada paso donde se realice una unificación, mostrar el conjunto de ecuaciones a unificar y la sustitución obtenida como resultado de la misma. λx. λy. λz. (z x) y z λx. x (w (λy.w y)) λx.λy. xy λx.λy. yx λx.(λx. x) λx.(λy. y)x (λz.λx. x (z (λy. z))) True Página 1 de 5 Paradigmas de Lenguajes de Programación 1er Cuatrimestre de 2014 Ejercicio 4 a) Extender el algoritmo de inferencia con las reglas necesarias para introducir los tipos Either tipo tipo y Maybe tipo, cuyos términos son análogos a los de Haskell. b) Utilizando estas reglas y el método del árbol, tipar la expresión: λx.if x then Just (Left 0) else Nothing Ejercicio 5 F Tomando en cuenta un nuevo tipo Vacı́o y la siguiente extensión del lenguaje: expr ::= . . . | error Extender el algoritmo de inferencia para que cualquier expresión que contenga algún error sea de tipo Vacı́o. Se asume que las reglas de tipado ya fueron adecuadamente modificadas. Ejercicio 6 F Tener en cuenta un nuevo tipo par definido como: tipo ::= . . . | htipo × tipoi Con expresiones nuevas definidas como: expr ::= . . . | hexpr, expri | π1 (expr) | π2 (expr) Y las siguientes reglas de tipado: Γ . M : hσ × τ i Γ . π1 (M ) : σ Γ.M:σ Γ.N:τ Γ . hM, N i : hσ × τ i Γ . M : hσ × τ i Γ . π2 (M ) : τ Adaptar el algoritmo de inferencia para que funcione sobre esta versión extendida. Ejercicio 7 Tipar la expresión (λf.hf,2i) (λx.x 1) utilizando la versión extendida del algoritmo del ejercicio 6. Ejercicio 8 F Intentar tipar la siguiente expresión utilizando la versión extendida del algoritmo del ejercicio 6. (λf.hf 2, f Truei) (λx.x) Mostrar en qué punto del mismo falla y por qué motivo. Ejercicio 9 F a) Extender el algoritmo de inferencia para soportar la inferencia de tipos de árboles binarios. En esta extensión del algoritmo sólo se considerarán los constructores del árbol. La sintaxis de esta extensión es la siguiente: σ ::= ... | ABσ M ::= ... | N ilσ | Binσ (M, N, O) Y sus reglas de tipado, las siguientes: Página 2 de 5 Paradigmas de Lenguajes de Programación 1er Cuatrimestre de 2014 Γ . M : ABσ Γ . O : ABσ Γ . N : σ Γ . Binσ (M, N, O) : ABσ Γ . N ilσ : ABσ Nota: la función Erase, que elimina la información de tipos que el inferidor se encargará de inferir, se extiende trivialmente para la sintaxis nueva: Erase(Nil σ ) Erase(Bin σ (M, N, O)) = Nil = Bin(Erase(M ), Erase(N ), Erase(O)) Recordar que una entrada válida para el algoritmo es un pseudo término con la información de tipos eliminada. Por ejemplo: (λx.Bin(N il, 5, Bin(N il, x, N il))) 5 b) Escribir la regla de tipado para el case de árboles binarios, y la regla análoga en el algoritmo de inferencia. Ejercicio 10 F Extender el algoritmo de inferencia W para que soporte el tipado del switch de números naturales, similar al de C o C++. La extensión de la sintaxis es la siguiente: M = . . . | switch M {case n1 : M1 . . . case nk : Mk default : Mk+1 } donde cada ni es un numeral (un valor de tipo Nat, como 0, succ(0), succ(succ(0)), etc.). Esto forma parte de la sintaxis y no hace falta verificarlo en el algoritmo. La regla de tipado es la siguiente: Γ . M : Nat ∀i, j(1 ≤ i, j ≤ k ∧ i 6= j ⇒ ni 6= nj ) Γ . N1 : σ ... Γ . Nk : σ Γ . switch (M ) {case n1 : N1 ... case nk : Nk default : N } : σ Γ.N :σ Por ejemplo, una expresión como: λx. switch (x) {case 0 : True default : False} deberı́a tipar a Nat → Bool. En cambio, la expresión: switch (3) {case 1 : 1 case 2 : 0 default : False} no tiene tipo, pues entre los casos hay números y booleanos. Y finalmente, la expresión: switch (3) {case 1 : 1 case 2 : 2 case 1 : 3 default : 0} tampoco tiene tipo, ya que el número 1 se repite entre los casos. Ejercicio 11 En este ejercicio extenderemos el algoritmo de inferencia para soportar operadores binarios. Dichos operadores se comportan de manera similar a las funciones, excepto que siempre tienen 2 parámetros y su aplicación se nota de manera infija. Para esto extenderemos la sintaxis y el sistema de tipos del cálculo lambda tipado de la siguiente manera: M ::= ... | ϕx : σ y : τ.M | hM N Oi σ ::= ... | Op(σ, τ → υ) Aquı́ ϕ es el constructor de operadores que liga las variables x (parámetro anterior al operador) e y (parámetro posterior) y hM N Oi es la aplicación del operador N a los parámetros M y O (lo ponemos entre h y i para evitar problemas de ambigüedad con la aplicación estándar). Op(σ, τ → υ), por otro lado, representa el tipo de los operadores cuyo parámetro anterior es de tipo σ, el posterior de tipo τ y dan como resultado un tipo υ. Las reglas de tipado que se incorporan son las siguientes: Γ ∪ {x : σ, y : τ } . M : υ Γ . ϕx : σ y : τ.M : Op(σ, τ → υ) Página 3 de 5 Paradigmas de Lenguajes de Programación 1er Cuatrimestre de 2014 Γ.M :σ Γ . N : Op(σ, τ → υ) Γ . hM N Oi : υ Γ.O :τ i. Dar la extensión al algoritmo necesaria para soportar el tipado de las nuevas expresiones. Recordar que el parámetro de entrada es un término sin anotaciones de tipos. ii. Aplicar el algoritmo extendido con el método del árbol para tipar: h(λx.succ(x)) (ϕxy.xy) 0i Ejercicio 12 Considerar el algoritmo de inferencia extendido para soportar listas: def W([ ]) = ∅ . [ ]s : [s], con s variable fresca. def W(M : N ) = SΓ1 ∪ SΓ2 . S(U : V ) : [Sσ], con: W(M ) = Γ1 . U : σ W(N ) = Γ2 . V : τ . . S = MGU({τ = [σ]} ∪ {α = β/x : α ∈ Γ1 ∧ x : β ∈ Γ2 }) i. Extender el algoritmo de inferencia para soportar expresiones de la forma “∃x in M/N ”. Γ ∪ {x : σ} . N : Bool Γ . M : [σ] Γ . ∃x in M/N : Bool ii. Aplicar el algoritmo extendido con el método del árbol para tipar las siguientes expresiones. Si alguna de ellas no tipa, indicar el motivo. i) ii) iii) iv) v) (λx.∃y in x/y)(0 : [ ]) (λx.∃y in x/y)(iszero(z) : [ ]) ∃x in [ ]/True ∃x in [ ]/(λy.True) ∃x in (0 : [ ])/iszero(x) Ejercicio 13 Se desea diseñar un algoritmo de inferencia de tipos para el cálculo-λ extendido con fórmulas proposicionales de la siguiente manera: M ::= · · · | ¬M | M ⊃ M | esTautologı́a(M ) σ := · · · | Prop Las reglas de tipado son: Γ . M : Prop tNeg Γ . ¬M : Prop Γ . M : Prop Γ . N : Prop tImp Γ . M ⊃ N : Prop Γ, x1 : Prop, . . . , xn : Prop . M : Prop fv(M ) = {x1 , . . . , xn } tTaut Γ . esTautologı́a(M ) : Bool Notar que esTautologı́a(M ) liga todas las variables libres de M . Por ejemplo, esTautologı́a(p ⊃ (q ⊃ p)) es un término cerrado y bien tipado (de tipo Bool). Página 4 de 5 Paradigmas de Lenguajes de Programación 1er Cuatrimestre de 2014 i. Extender el algoritmo de inferencia para admitir las expresiones incorporadas al lenguaje, de tal manera que implemente las reglas de tipado tNeg, tImp y tTaut. ii. Aplicar el algoritmo extendido con el método del árbol para tipar las siguientes expresiones (exhibiendo siempre las sustituciones utilizadas). Si alguna de ellas no tipa, indicar el motivo. λy.¬((λx.¬x)(y ⊃ y)) (λx.esTautologı́a(if x then y else z))True Página 5 de 5