Práctica 3 - actualizada el 19 de abril de 2016

Anuncio
Paradigmas de Lenguajes de Programación
1er Cuatrimestre de 2016
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).
Gramáticas a tener en cuenta:
Términos anotados
M ::= x | λx : σ.M | M M | True | False | if M then M else M | 0 | succ(M ) | pred(M ) | isZero(M ) Donde
la letra x representa un nombre de variable arbitrario. Tales nombres se toman de un conjunto infinito
dado X = {w, w1 , w2 , . . . , x, x1 , x2 , . . . , y, y1 , y2 , . . . , f, f1 , f2 , . . . }
Términos sin anotaciones
M 0 ::= x | λx.M 0 | M 0 M 0 | True | False | if M 0 then M 0 else M 0 | 0 | succ(M 0 ) | pred(M 0 ) | isZero(M 0 )
Tipos
σ ::= Bool | Nat | σ → σ | s
Donde la letra s representa una variable de tipos arbitraria. Tales nombres se toman de un conjunto
infinito dado T = {s, s1 , s2 , . . . , t, t1 , t2 , . . . , . . . }
Ejercicio 1
Determinar qué expresiones son sintácticamente válidas y, para las que sean, indicar a qué gramática pertenecen.
i. λx : Bool.succ(x)
v. s
vi. s → (Bool → t)
ii. λx.isZero(x)
iii. s → σ
vii. λx : s1 → s2 .if 0 then True else 0 succ(True)
viii. Erase(λf : Bool → s.λy : Bool.f y)
iv. Erase(f y)
Ejercicio 2
Determinar el resultado de aplicar la sustitución S a las siguientes expresiones
i. S = {t ← Nat}
S({x : t → Bool})
ii. S = {t1 ← t2 → t3 , t ← Bool} S({x : t → Bool}) . S(λx : t1 → Bool.x) : S(Nat → t2 )
Ejercicio 3 F
Determinar el resultado de aplicar el MGU (“most general unifier”) sobre las ecuaciones planteadas a continuación.
En caso de tener éxito, mostrar la sustitución resultante.
Página 1 de 6
Paradigmas de Lenguajes de Programación
1er Cuatrimestre de 2016
.
v. MGU {t2 → t1 → Bool = t2 → t3 }
.
.
vi. MGU {t1 → Bool = Nat → Bool, t1 = t2 → t3 }
.
.
vii. MGU {t1 → Bool = Nat → Bool, t2 = t1 → t1 }
.
.
viii. MGU {t1 → t2 = t3 → t4 , t3 = t2 → t1 }
.
i. MGU {t1 → t2 = Nat → Bool}
.
ii. MGU {t1 → t2 = t3 }
.
iii. MGU {t1 → t2 = t2 }
.
iv. MGU {(t2 → t1 ) → Bool = t2 → t3 }
Ejercicio 4
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 5
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 6 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 2 de 6
Paradigmas de Lenguajes de Programación
1er Cuatrimestre de 2016
Ejercicio 7 (Numerales de Church)
Indicar tipos σ y τ apropiados de modo que los términos de la forma λy : σ.λx : τ.y n (x) resulten tipables para
todo n natural. El par (σ, τ ) debe ser el mismo para todos los términos. Observar si tienen todos el mismo
tipo. Notación: M 0 (N ) = N, M n+1 (N ) = M (M n (N )). Sugerencia: empezar haciendo inferencia para n = 2 –
es decir, calcular W(λy.λx.y(yx)) – y generalizar el resultado.
Ejercicio 8
i. Utilizar el algoritmo de inferencia sobre la siguiente expresión: λy.(x y) (λz.x2 )
ii. Una vez calculado, demostrar (utilizando chequeo de tipos) que el juicio encontrado es correcto.
iii. ¿Qué ocurrirı́a si x2 fuera x?
Ejercicio 9 F
Tener en cuenta un nuevo tipo par definido como: σ ::= . . . | hσ × σi
Con expresiones nuevas definidas como: M ::= . . . | hM , M i | π1 (M ) | π2 (M )
Y las siguientes reglas de tipado:
Γ . M : hσ × τ i
Γ . π1 (M ) : σ
Γ.M:σ Γ.N:τ
Γ . hM, N i : hσ × τ i
Γ . M : hσ × τ i
Γ . π2 (M ) : τ
i. Adaptar el algoritmo de inferencia para que funcione sobre esta versión extendida.
ii. Tipar la expresión (λf.hf,2i) (λx.x 1) utilizando la versión extendida del algoritmo.
iii. Intentar tipar la siguiente expresión utilizando la versión extendida del algoritmo.
(λf.hf 2, f Truei) (λx.x)
Mostrar en qué punto del mismo falla y por qué motivo.
Ejercicio 10
a) Extender el sistema de tipado y el algoritmo de inferencia con las reglas necesarias para introducir los
tipos Either σ σ y
Maybe σ, 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 11 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)
Página 3 de 6
Paradigmas de Lenguajes de Programación
1er Cuatrimestre de 2016
Y sus reglas de tipado, las siguientes:
Γ . 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 de manera acorde 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 12 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 13
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 υ.
Página 4 de 6
Paradigmas de Lenguajes de Programación
1er Cuatrimestre de 2016
Las reglas de tipado que se incorporan son las siguientes:
Γ ∪ {x : σ, y : τ } . M : υ
Γ . ϕx : σ y : τ.M : Op(σ, τ → υ)
Γ.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 14
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) (λx.∃y in x/y)(0 : [ ])
ii) (λx.∃y in x/y)(iszero(z) : [ ])
iii) ∃x in [ ]/True
iv) ∃x in [ ]/(λy.True)
v) ∃x in (0 : [ ])/iszero(x)
Ejercicio 15
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
Página 5 de 6
Paradigmas de Lenguajes de Programación
1er Cuatrimestre de 2016
Γ, 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).
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
Ejercicio 16 F
En este ejercicio modificaremos el algoritmo de inferencia para incorporar la posibilidad de utilizar letrec en
nuestro cálculo.
M ::= . . . | letrec f = M in N
letrec permite por ejemplo representar el factorial de 10 de la siguiente manera:
letrec f = (λ x : Nat . if isZero(x) then 1 else x × f (pred(x))) in f 10
Para ello se agrega la siguiente regla de tipado:
Γ ∪ {f : π → τ } . M : π → τ
Γ ∪ {f : π → τ } . N : σ
Γ . letrec f = M in N : σ
Suponiendo que se propone el siguiente pseudocódigo:
def
W(letrec f = M in N ) = Γ . S (letrec f = M 0 in N 0 ) : S σ
donde
W(M ) = Γ1 . M 0 : π → τ
W(N ) = Γ2 . N 0 : σ
τ1 = ρ/f : ρ ∈ Γ1
τ2 = δ/f : δ ∈ Γ2
.
S = MGU {τ1 = τ2 , COMPLETAR}
Γ = S Γ1 ∪ S Γ2
i. Explicar cuál es el error en los llamados recursivos. Dar un ejemplo que deberı́a tipar y no lo hace debido
a este error.
ii. Explicar cuál es el error en el pseudocódigo con respecto la definición de τ1 y τ2 . Dar un ejemplo que
deberı́a tipar y no lo hace debido a este error.
iii. El contexto Γ ¿puede contener a f? ¿Es un comportamiento deseable? Mostrar un ejemplo donde esto trae
conflictos (ayuda: usar letrec dentro de un término más grande).
iv. Reescribir el pseudocódigo para que funcione correctamente (corregir los errores y completar la definición
de S).
Página 6 de 6
Descargar