Launchbury present´o en [Lau93] una sem´antica natural perezosa (call-by-need, ver Secci´on 2.1.2) que ha sido de gran importancia en el paradigma funcional. En el texto el autor explica que la pereza implica un lenguaje no estricto, que ciertas reducciones sean compartidas y que la evaluaci´on termine al encontrar una λ-abstracci´on. Otros lenguajes no estrictos que se usan en la actualidad, son, por ejemplo, Miranda [mir15] o Haskell[has15]. El trabajo de Launchbury ha sido citado con frecuencia y ha servido como base para otros trabajos y extensiones [BKT00, HO02, NH09, Ses97, vEdM07]. El ´exito de este trabajo radica en su simplicidad. Las expresiones se eval´uan dentro de un contexto que se
x ∈ Var
e ∈ Exp ::= x | λx.e | (e x) | let {xi = ei}ni=1 ine
Figura 2.4: Sintaxis restringida del λ-c´alculo extendido
(λx.e)∗ = λx.(e∗)
x∗ = x
(let{xi= ei}ni=1 in e)∗ = let {xi = (e∗i)}ni=1 in(e∗)
(e1 e2)∗ = (e∗ 1) e2 si e2 es una variable let y = (e∗2) in (e∗1) y e.o.c.,
siendo y una variable fresca
Figura 2.5: Normalizaci´on del λ-c´alculo extendido
representa como un conjunto de pares (variable/expresi´on) donde toda la informaci´on es compartida. Adem´as, estos pares se actualizan sustituyendo las expresiones por su valor una vez calculado. De esta forma se modeliza la evaluaci´on perezosa.
Launchbury trabaja con un λ-c´alculo extendido con declaraciones locales recursivas como muestra la Figura 2.4, en el que se aplica un proceso de normalizaci´on en dos pasos: En primer lugar, se realiza una α-conversi´on, de forma que todas las variables ligadas mediante las declaraciones locales y las λ-abstracciones se renombran con variables frescas. De este modo todas las variables locales tienen nombres distintos.
En segundo lugar, se fuerza a que los argumentos de las funciones sean variables, tal como se muestra en la Figura 2.5. Este cambio se denota por e∗.
Este proceso de normalizaci´on simplifica considerablemente las definiciones de las reglas de la sem´antica operacional. Por un lado, el hecho de usar nombres distintos hace que el ´
ambito de aplicaci´on sea irrelevante. Por otro, la restricci´on sobre las aplicaciones consigue que no haya que introducir clausuras nuevas en la sem´antica.
En la sem´antica natural con estrategia call-by-need que define Launchbury, los juicios o sentencias son de la forma
Γ : e⇓ ∆ : w,
es decir, se eval´ua la expresi´on e en el contexto del heap Γ, que reduce a un valor w en el contexto del heap ∆. Los heaps son funciones parciales de variables a expresiones. Se denomina ligadura a un par (variable, expresi´on) y se denota por x 7→ e. Los valores (w ∈ Val) son expresiones en forma normal d´ebil de cabeza (whnf, del ingl´es weak-head- normal-form), es decir, con una λ en cabeza. Las reglas sem´anticas se muestran en la Figura 2.6. Durante la evaluaci´on de una expresi´on, se pueden a˜nadir al heap nuevas liga- duras (regla Let). As´ı mismo, algunas de las ya existentes pueden ser actualizadas con sus correspondientes valores ya calculados (regla Var). La regla Lam indica que las expresio- nes ya evaluadas se reducen a ellas mismas sin modificar el contexto de evaluaci´on. A pesar de la normalizaci´on, en la regla Var es necesaria una α-conversi´on del valor final obtenido que viene representado por ˆw. Este renombramiento evita colisiones con los nombres ya
Lam Γ : λx.e⇓ Γ : λx.e App Γ : e⇓ Θ : λy.e 0 Θ : e0[x/y]⇓ ∆ : w Γ : (e x)⇓ ∆ : w Var Γ : e⇓ ∆ : w (Γ, x7→ e) : x ⇓ (∆, x 7→ w) : ˆw Let (Γ,{xi 7→ ei}ni=1) : e⇓ ∆ : w Γ : let{xi = ei}ni=1 ine⇓ ∆ : w
Figura 2.6: Sem´antica natural
[[λx.e]]ρ = Fn(λν.[[e]]ρt{x7→ν})
[[e x]]ρ = ([[e]]ρ)↓Fn ([[x]]ρ) [[x]]ρ = ρ(x)
[[let x1= e1. . . xn= en in e]]ρ = [[e]]{{x17→e1...xn7→en}}ρ
Figura 2.7: Sem´antica denotacional
existentes y se justifica por la convenci´on de variables de Barendregt [Bar84]. La regla App reduce primero el t´ermino e y tras obtener un valor (es decir, una λ-abstracci´on) realiza la aplicaci´on mediante una β-reducci´on, evaluando la expresi´on resultante. Por ´ultimo, la regla Let, adem´as de introducir en el heap las declaraciones locales, eval´ua el cuerpo de la expresi´on. N´otese que debido a la normalizaci´on realizada previamente no puede haber conflictos entre las variables cuando ´estas son introducidas en el heap.
A su vez, Launchbury tambi´en dot´o de significado denotacional a las expresiones del λ-c´alculo bas´andose en el modelo de Abramsky [Abr90]. La funci´on sem´antica de la que parte es la siguiente:
[[−]] : Exp → Env → Value
donde Exp representa las expresiones del λ-c´alculo (Figura 2.4), Value un dominio apro- piado que satisface la ecuaci´on Value = [Value → Value]⊥ (explicado en la Secci´on 2.3), y
Env contiene los entornos de evaluaci´on de las variables libres. Los entornos son funciones de variables a valores, es decir,
ρ∈ Env = Var → Value.
La funci´on sem´antica se incluye en la Figura 2.7, donde se utiliza una funci´on que relaciona los heaps con los entornos:
{{−}} : Heap → Env → Env
Esta funci´on captura la recursi´on generada por las declaraciones locales y viene definida por:
{{x1 7→ e1. . . xn7→ en}}ρ = µρ0.ρt (x17→ [[e1]]ρ0. . . xn7→ [[en]]ρ0)
En esta definici´on el operador de menor punto fijo viene representado por µ. Esta funci´on puede verse como un modificador de entornos que s´olo cobra sentido si los entornos y los heaps son consistentes; es decir, siempre que una variable aparezca ligada tanto en el entorno como en el heap, entonces estar´a ligada a valores para los que exista una cota superior.
Var (Γ, x7→ e) : ˆe ⇓ ∆ : w
(Γ, x7→ e) : x ⇓ ∆ : w App
Γ : e⇓ Θ : λy.e0 (Θ, y 7→ x) : e0 ⇓ ∆ : w
Γ : (e x)⇓ ∆ : w
Figura 2.8: Sem´antica natural alternativa
N [[e]]σ ⊥ = ⊥
N [[λx.e]]σ (S k) = Fn(λν.N [[e]]σt{x7→ν} )
N [[e x]]σ (S k) = (N [[e]]σ k)↓Fn (N [[x]]σ ) k N [[x]]σ (S k) = σ x k
N [[let x1= e1. . . xn= en in e]]σ (S k) = N [[e]]µσ0 (σtx17→N [[e1]]σ0 t···txn7→N [[en]]σ0 ) k
Figura 2.9: Sem´antica denotacional con recursos.
Launchbury define un orden sobre los entornos de forma que ρ ≤ ρ0 si ρ0 liga m´as
variables que ρ, pero las que est´en en ambos entornos deben estar ligadas a los mismos valores. Formalmente,∀x ∈ Var . ρ(x) 6= ⊥ ⇒ ρ(x) = ρ0(x).
2.4.1 Propiedades
Launchbury establece la correcci´on (Secci´on 2.2.1) de las reglas operacionales con res- pecto a la sem´antica denotacional expuesta. El teorema de correcci´on afirma que las re- ducciones preservan el significado de los t´erminos y solamente se modifica el significado de los heaps a˜nadiendo nuevas ligaduras, si ello fuera necesario.
Teorema 1 (Correcci´on de la sem´antica natural.)
Si Γ : e⇓ ∆ : z entonces para todo entorno ρ, [[e]]{{Γ}}ρ = [[z]]{{∆}}ρ y {{Γ}}ρ≤ {{∆}}ρ.
Dado que existen ciertas diferencias entre la sem´antica operacional y la sem´antica denotacional definidas, Launchbury introduce dos nuevas sem´anticas m´as pr´oximas entre s´ı para establecer la adecuaci´on computacional (Secci´on 2.2.1). En primer lugar, modifica la sem´antica natural cambiando las reglas para la variable y la aplicaci´on por las expuestas en la Figura 2.8. En esta versi´on de la sem´antica no hay actualizaci´on de ligaduras y la aplicaci´on se realiza a trav´es de indirecciones, en vez de mediante una β-reducci´on. Las nuevas reglas hacen que los contextos de evaluaci´on se ajusten m´as a los entornos de la sem´antica denotacional.
En segundo lugar, introduce una sem´antica denotacional basada en recursos, en la que, si no se dispone de recursos suficientes, los t´erminos quedan indefinidos. En esta versi´on con recursos la funci´on sem´antica toma un nuevo argumento, los recursos, que se van consumiendo por cada nivel sint´actico evaluado. De esta forma se consigue que la sem´antica denotacional se ajuste m´as a la aplicaci´on de las reglas de la sem´antica operacional. Las nuevas cl´ausulas denotacionales se muestran en la Figura 2.9.
Finalmente, Launchbury demuestra la adecuaci´on computacional de la sem´antica ope- racional alternativa con respecto a la sem´antica denotacional de recursos.
Teorema 2 (Adecuaci´on computacional de la sem´antica alternativa.) Si existe m∈ N tal que N [[e]]µσ.(x17→N [[e1]]σ t···txn7→N [[en]]σ ) (S
m ⊥) 6=⊥, entonces existen
E ::= x| \x.E | E1 E2| E1#E2 | let {xi= Ei}ni=1 inE
| new(y, x)E| x ! E1 parE2 | E1 ./ E2 | Λ[x1 : x2].E1dcE2| L
L ::= nil| [E1 : E2]
Figura 2.10: Sintaxis de Jauja