4. FLC: una sem´ antica operacional de bajo nivel
4.2. Relaci´ on con CRWL
5.1.2. Reglas de la let reescritura
de (LetIn) comparada con la regla (Brw) de la figura 5.1 (p´agina 78), es que al hacer la suspensi´on no perdemos informaci´on: si m´as adelante se necesita evaluar la expresi´on sus- pendida para continuar la derivaci´on podremos evaluar dicha expresi´on mediante (Contx) y luego propagar el resultado mediante (Bind). Esta ´ultima regla es segura respecto a la elecci´on en invocaci´on porque s´olo propaga c-t´erminos, es decir, o bien valores ya calculados (pertenecientes a FCTerm), o bien valores calculados excepto por alguna suspensi´on (perte- necientes a CT erm\F CT erm), suspensiones que el c´alculo maneja con seguridad respecto a la elecci´on en invocaci´on. Por otra parte si la ligadura correspondiente a la expresi´on suspendida desaparece durante la evaluaci´on, la regla (Elim) se encarga de la recogida de basura. Esta regla es necesaria porque las formas normales deseadas son c-t´erminos. Por ´
ultimo la regla (Flat) es necesaria para aplanar los let’s anidados, lo que es imprescindible para evitar que algunas derivaciones se bloqueen incorrectamente, o se vean forzadas a di- vergir. Por ejemplo dado el programa P = {loop → loop, g(s(X)) → 1}, podemos obtener g(s(loop)) →2l let X = (let Y = loop in s(Y )) in g(X), aplicando dos veces (LetIn). A partir de ah´ı, sin (Flat), la ´unica reducci´on posible es en loop mediante (Fapp), mientras que aplicando (Flat) podemos lograr let X = (let Y = loop in s(Y )) in g(X) →llet Y =
loop in let X = s(Y ) in g(X) →l let Y = loop in g(s(Y )) →l let Y = loop in 1 →l 1,
usando (Bind) y (Elim) en los dos ´ultimos pasos.
N´otese que gracias a la convenci´on de variables la condici´on “Yp no aparece libre en e3” en
(Flat) no es necesaria, pero se incluye para que las reglas del c´alculo sean independientes de la convenci´on de variables. Sin embargo la condici´on “Xp no aparece libre en e2” de
la regla (Elim) puede o no cumplirse independientemente de la convenci´on de variables y por tanto siempre ser´a necesario incluirla.
En todo caso es importante hace notar que este c´alculo no hace uso en absoluto del valor sem´antico ⊥, siendo ´esta una de sus principales diferencias respecto a CRWL, que basa en ⊥ todo su montaje para lograr una sem´antica no estricta.
El par (LExp, →l) constituye un ARS, al cual podemos por tanto aplicar la termino-
log´ıa usual: →0l, →+l , →∗l, . . . En ocasiones utilizaremos la notaci´on P ` e →l e0 para
indicar que se utiliz´o en programa P para hacer la reducci´on. Por ´ultimo, utilizaremos la notaci´on “(regla∗)” para referirnos a cero o m´as aplicaciones de la regla especificada.
Algunos ejemplos de derivaciones con este c´alculo (se indica la regla aplicada excepto en el caso de (Contx) en que su aplicaci´on queda impl´ıcita y se indica la regla usada en la premisa):
Ejemplo 5.1.1.
P = {coin → 0, coin → 1, pair(X) → (X, X)}
double(coin) →l let Xp = coin in pair(Xp) (LetIn)
→llet Xp = coin in (Xp, Xp) (Fapp)
→llet Xp = 0 in (Xp, Xp) (Fapp)
→l(0, 0) (Bind)
double(coin) →l let Xp = coin in pair(Xp) (LetIn)
→llet Xp = coin in (Xp, Xp) (Fapp)
→llet Xp = 1 in (Xp, Xp) (Fapp)
86 5. Let-reescritura
Ejemplo 5.1.2.
P = {ones → 1 : ones, head(X : Xs) → X}
head(ones) →llet Xp = ones in head(Xp) (LetIn)
→l let Xp = 1 : ones in head(Xp) (Fapp)
→l let Xp = (let Yp = ones in 1 : Yp) in head(Xp) (LetIn)
→l let Yp = ones in let Xp= 1 : Yp in head(Xp) (Flat)
→l let Yp = ones in head(1 : Yp) (Bind)
→l let Yp = ones in 1 (Fapp)
→l 1 (Elim)
Ejemplo 5.1.3.
P = {coin → 0, coin → 1
, repeat(X) → X : repeat(X), heads(X : Y : Y s) → (X, Y )}
heads(repeat(coin)) →l let Xp = repeat(coin) in heads(Xp) (LetIn)
→llet Xp = (let Yp = coin in repeat(Yp)) in heads(Xp) (LetIn)
→llet Yp = coin in let Xp= repeat(Yp) in heads(Xp) (Flat)
→llet Yp = coin in let Xp= Yp : repeat(Yp) in heads(Xp) (Fapp)
→llet Yp = coin in let Xp= (let Zp = repeat(Yp) in Yp : Zp) in heads(Xp) (LetIn)
→llet Yp = coin in let Zp = repeat(Yp) in let Xp = Yp : Zp in heads(Xp) (Flat)
→llet Yp = coin in let Zp = repeat(Yp) in heads(Yp : Zp) (Bind)
→llet Yp = coin in let Zp = Yp: repeat(Yp) in heads(Yp: Zp) (Fapp)
→llet Yp = coin in let Zp = (let Up = repeat(Yp) in Yp : Up) in heads(Yp : Zp) (LetIn)
→llet Yp = coin in let Up = repeat(Yp) in let Zp = Yp: Up in heads(Yp: Zp) (Flat)
→llet Yp = coin in let Up = repeat(Yp) in heads(Yp : Yp: Up) (Bind)
→llet Yp = coin in let Up = repeat(Yp) in (Yp, Yp) (Fapp)
→llet Yp = coin in (Yp, Yp) (Elim)
→llet Yp = 0 in (Yp, Yp) (Fapp)
→l(0, 0) (Bind)
Otros comentarios que podr´ıamos hacer respecto a este c´alculo:
En general puede existir m´as de una secuencia de reducci´on desde una expresi´on a un c-t´ermino alcanzable desde ella. Por ejemplo, usando el programa del ejemplo 5.1.1, la derivaci´on double(coin) →ldouble(0) →l(0, 0) parte de la misma expresi´on y llega
al mismo c-t´ermino que la primera derivaci´on de dicho ejemplo pero es distinta a ´
esta. Es decir, hay una cierta cantidad de indeterminismo introducido por la let -reescritura, que se acotar´a en trabajos futuros mediante la introducci´on de una estrategia de reducci´on apropiada.
Respecto a la regla (LetIn), podr´ıamos haber optado por una definici´on m´as sencilla que no impusiera restricciones sobre la forma de la expresi´on suspendida:
(LetIn’) h(. . . , e, . . .) →llet Xp= e in h(. . . , Xp, . . .), si h ∈ CS ∪ F S, e 6∈ V y con
Xp∈ P V ar fresca
El problema de esta definici´on es que para cualquier programa podr´ıamos encon- trar derivaciones no terminantes, como por ejemplo s(z) →l let X = z in s(X) →l
5.1.2 Reglas de la let-reescritura 87
s(z) →l let X = z in s(X) →l . . . (para s ∈ CS1, z ∈ CS0), y nos interesa que la
let -reescritura sea capaz de expresar propiedades operacionales como la terminaci´on. Por otra parte no podemos solucionar el problema de (LetIn’) simplemente sustitu- yendo en esta regla e por f (e), quedando:
(LetIn”) h(. . . , f (e), . . .) →l let Xp = f (e) in h(. . . , Xp, . . .), si h ∈ CS ∪ F S,
f ∈ F S y con Xp ∈ P V ar fresca
porque algunas derivaciones quedar´ıan bloqueadas, como podemos ver en el siguiente contraejemplo:
Contraejemplo 5.1.1.
P = {f → s(loop), loop → loop, g(s(X)) → 1}
g(f ) →l g(s(loop)) (Fapp)
→lg(let Xp= loop in s(Xp)) (LetIn)
→llet Yp = (let Xp = loop in s(Xp)) in g(Yp) (LetIn)
→llet Xp = loop in let Yp = s(Xp) in g(Yp) (Flat)
→llet Xp = loop in g(s(Xp)) (Bind)
→llet Xp = loop in 1 (Fapp)
→l1 (Elim)
En esta derivaci´on es imprescindible que (LetIn) nos permita suspender tambi´en construcciones let, sino la segunda aplicaci´on de (LetIn) no habr´ıa sido posible y el c´omputo se hubiera quedado atascado en la expresi´on g(let Xp = loop in s(Xp)),
solamente pudiendo aplicar (Fapp) sobre loop.
En cuanto a la definici´on 5.1.5(p´agina 84) que dimos para las c-instancias tota- les de reglas de programa, coment´abamos antes que ´esta nos permite instanciar variables extra con variables producidas, lo que en un principio puede parecer peli- groso. Lo cierto es que este hecho puede hacer que durante una derivaci´on se llegue a situaciones como esta:
P = {f = X, f st(X, Y ) = X}
f st(1, f ) →lf st(1, Xp) variable producida libre
N´otese en cambio que la siguiente situaci´on s´ı que es evitada por el c´alculo puede darse es
P = {f = X, f st(X, Y ) = X}
let Xp = 1 in f st(f, 2) →llet Xp = 1 in f st(Xp, 2) variable extra capturada
ya que la convenci´on de variables nos asegura que no habr´a captura de variables. Por tanto todas las variables producidas introducidas instanciando variables extra ser´an variables producidas libres en cualquier contexto.
Aunque la presencia de variables producidas libres es una anomal´ıa no muy placen- tera, afortunadamente no es peligrosa porque si una derivaci´on prospera con una variable producida libre es porque, durante la derivaci´on, o bien no ha aparecido como argumento de ninguna aplicaci´on de funci´on reducida por (Fapp), o si lo ha hecho ha encajado siempre con la posici´on de una variable en el lado izquierdo de
88 5. Let-reescritura
la regla utilizada (porque una variable s´olo encaja en un patr´on que sea tambi´en una variable). En cualquier caso si en vez de instanciar con una variable producida lo hubi´eramos hecho con una variable de FVar hubi´eramos podido construir una derivaci´on exactamente igual excepto por el reemplazo de la variable producida por la nueva variable libre, en cada expresi´on de la derivaci´on. En secciones posteriores veremos como esta conjetura informal acabar´a confirm´andose, y que la instanciaci´on libre de variables extra no conlleva problemas de incorrecci´on de la let -reescritura. En cambio, una definici´on alternativa que no permitiera instanciar variables extra con variables producidas s´ı que nos podr´ıa traer problemas de incompletitud. Supon- gamos que cambiamos la definici´on de c-instancia total de regla de programa para que sea la siguiente:
[P] = {(l → r)σ | (l → r) ∈ P, σ ∈ CSubst, vRan(σ|\F V (l)) ∩ P V ar = ∅}
obligando por tanto a que las variables extra se instancien con elementos de F CT erm. Utilizando esta definici´on desincronizar´ıamos las definiciones de instancia de regla para CRW L y para la let -reescritura, lo que conllevar´ıa problemas de incompletitud de la let -reescritura respecto a CRWL, como podemos ver en el siguiente contra- ejemplo:
Contraejemplo 5.1.2.
P = {f (X) = Y } P `CRW Lf (1) → Xp
f (1) 6→lXp
Aunque podr´ıamos forzar a que CRWL trabajara s´olamente con FVar, para que no pueda instanciar variables extra con variables producidas, eso complicar´ıa innecesa- riamente los c´alculos y emborronar´ıa los resultados, por lo que seguiremos utilizando la definici´on 5.1.5.
En cuanto a las c´ascaras, podr´ıamos haber definido de la siguiente manera el caso para los let’s:
|let X = e1 in e2| = |e2|[X/ ⊥]
La desventaja de esta ´ultima definici´on es que con ella no es cierto que e →l e0
implique |e| v |e0|, debido a la regla (LetIn), como podemos ver en el siguiente contraejemplo:
Dado c(let Xp = 2 in s(Xp)) →llet Yp = (let Xp = 2 in s(Xp)) in c(Yp)
tenemos que |c(let Xp= 2 in s(Xp))| = c(s(Xp)[Xp/ ⊥]) = c(s(⊥))
mientras que |let Yp = (let Xp = 2 in s(Xp)) in c(Yp)| = c(Yp)[Yp/ ⊥] = c(⊥)
Como esa es una propiedad interesante que demostraremos m´as adelante, seguiremos utilizando la definici´on5.1.4(p´agina 83).