Cálculo lambda

Revisión del 19:36 20 jun 2019 de Javiermartin jc (discusión | contribuciones) (Texto reemplazado: «<div align="justify">» por «»)
(dif) ← Revisión anterior | Revisión actual (dif) | Revisión siguiente → (dif)
Cálculo Lambda
Información sobre la plantilla
Concepto:Es el lenguaje de programación mas pequeño consiste en transformación simple(sustituir variables) y en definir funciones

Cálculo Lambda. Es el más pequeño lenguaje universal de programación, consiste en en una regla de transformación simple (sustituir variables) y un esquema simple para definir funciones.

El cálculo lambda se puede decir que es equivalente a las máquinas Turing porque es capaz de evaluar y expresar cualquier función computable. Church había querido hacer un sistema formal completo para modelizar la matemática pero después separó el cálculo lambda y lo ideó para que estudiara la computabilidad.

Surgimiento

Originalmente, Church había tratado de construir un sistema formal completo para modelizar la Matemática; pero cuando éste se volvió susceptible a la paradoja de Russell, separó del sistema al cálculo lambda y lo usó para estudiar la computabilidad, culminando en la respuesta negativa al problema de la parada.

Definición Informal

Considérese las siguientes dos Funciones. Por un lado, la Función Identidad I(x) = x, que toma un único argumento, x, e inmediatamente devuelve x. Por otro lado, la función suma S(x,y) = x + y, que toma dos argumentos, x e y, y devuelve la suma de ambos: x + y. Usando estas dos funciones como ejemplo, es posible hacer algunas observaciones útiles acerca de varias ideas fundamentales del cálculo lambda.

La primera observación es que las funciones no necesitan ser explícitamente nombradas. Esto es, la función S(x,y) = x + y puede ser reescrita como una función anónima: x,y → x + y (que se lee: «el par de x e y se mapea a x + y»). Del mismo modo, I(x) = x puede ser reescrita de forma anónima como x → x, que se lee: «el argumento x se mapea a sí mismo».

La segunda observación es que el nombre que se asigne a los argumentos de la función es generalmente irrelevante. Esto es, x → x e y → y expresan la misma función: la función identidad. Del mismo modo, x,y → x + y y u,v → u + v expresan la misma función: la función suma.

Una tercera observación es que toda función que requiere dos argumentos, como por ejemplo la función suma, puede ser reescrita como una función que acepta un único argumento, pero que devuelve otra función, la cual a su vez acepta un único argumento. Por ejemplo, x,y → x + y puede ser reescrita como x → (y → x + y). Esta transformación se conoce como currificación, y puede generalizarse para funciones que aceptan cualquier número de argumentos. Esta puede parecer oscuro, pero se entiende mejor mediante un ejemplo. Considérese la función suma no currificada:

x,y → x + y

Al tomar a los números 2 y 3 como argumentos, se obtiene:

2 + 3

Lo cual es igual a 5. Considérese ahora la versión currificada de la función:

x → (y → x + y)

Si se toma al número 2 como argumento, se obtiene la función:

y → 2 + y

Y tomando luego al número 3 como argumento, se obtiene:

2 + 3

Lo cual es igual a 5. De modo que la versión currificada devuelve el mismo resultado que la versión no currificada. En el cálculo lambda, todas las expresiones representan funciones anónimas de un sólo argumento.

Una cuarta observación es que una función puede aceptar como argumento a otra función, siempre y cuando esta otra función tenga ella misma un sólo argumento. Por ejemplo, la función identidad puede aceptar como argumento a la función suma (currificada). Es decir, se toma a la función x → (y → x + y) y se la pone como argumento en z → z. El resultado será obviamente x → (z → x + z), (igual a la x → (y → x + y)) pues la función identidad siempre devuelve lo mismo que se le da.

En el cálculo lambda, las funciones están definidas por expresiones lambda, que dicen qué se hace con su argumento. Por ejemplo, la función "sumar 2",  f(x) = x + 2  se expresa en cálculo lambda así:  λ x. x + 2  (o, equivalentemente,  λ y. y + 2 ya que el nombre de su argumento no es importante). Y el número f(3) sería escrito como  (λ x. x + 2) 3. La aplicación de funciones es asociativa a izquierda:  f x y = (f x) y.  Considerando la función que aplica una función al número 3: λ f. f 3. , podemos pasarle "sumar 2", quedando así:  (λ f. f 3) (λ x. x + 2)

Las tres expresiones:

f. f 3)(λ x. x + 2)   ,    (λ x. x + 2) 3    y    3 + 2   

son equivalentes.

No todas las expresiones lambda pueden ser reducidas a un "valor" definido. Considérese la siguiente:

x. x x) (λ x. x x)

ó

x. x x x) (λ x. x x x)

tratar de reducir estas expresiones sólo lleva a encontrase con la misma expresión o algo más complejo.  (λ x. x x es conocido como ω combinador;  ((λ x. x x) (λ x. x x))  se conoce como Ω,  ((λ x. x x x) (λ x. x x x))  como Ω2, etc.

Definición formal

Sintaxis

En el cálculo lambda, una expresión o término se define recursivamente a través de las siguientes reglas de formación:

  1. Toda variable es un término: x, y, z, u, v, w, x1, x2, y9,...
  2. Si t es un término y x es una variable, entonces (λx.t) es un término (llamado una abstracción lambda).
  3. Si t y s son términos, entonces (ts) es un término (llamado una aplicación lambda).
  4. Nada más es un término.

Según estas reglas de formación, las siguientes cadenas de caracteres son términos:

x
(xy)
(((xz)y)x)
(λx.x)
((λx.x)y)
(λz.(λx.y))
((x(λz.z))z)

Por convención se suelen omitir los paréntesis externos, ya que no cumplen ninguna función de desambiguación. Por ejemplo se escribe (λz.z)z en vez de ((λz.z)z), y se escribe x(y(zx)) en vez de (x(y(zx))). Además se suele adoptar la convención de que la aplicación de funciones es asociativa hacia la izquierda. Esto quiere decir, por ejemplo, que xyzz debe entenderse como (((xy)z)z), y que (λz.z)yzx debe entenderse como ((((λz.z)y)z)x).

Las primeras dos reglas generan funciones, mientras que la última describe la aplicación de una función a un argumento. Una abstracción lambda λx.t representa una función anónima que toma un único argumento, y se dice que el signo λ liga la variable x en el término t. En cambio, una aplicación lambda ts representa la aplicación de un argumento s a una función t. Por ejemplo, λx.x representa la Función Identidad x → x, y (λx.x)y representa la función identidad aplicada a y. Luego, λx.y representa la función constante x → y, que develve y sin importar qué argumento se le dé.

Las expresiones lambda no son muy interesantes por sí mismas. Lo que las hace interesantes son las muchas nociones de equivalencia y reducción que pueden ser definidas sobre ellas.

Variables libres y ligadas

Las apariciones (ocurrencias) de variables en una expresión son de tres tipos:

  1. Ocurrencias de ligadura (binders)
  2. Ocurrencias ligadas (bound occurrences)
  3. Ocurrencias libres (free occurrences)

Las variables de ligadura son aquellas que están entre el λ y el punto. Por ejemplo, siendo E una expresión lambda:

 (λ x y z. E) Los binders son x,y y z.

El binding de ocurrencias de una variable está definido recursivamente sobre la estructura de las expresiones lambda, de esta manera:

  1. En expresiones de la forma  V,  donde V es una variable, V es una ocurrencia libre.
  2. En expresiones de la forma  λ V. E,  las ocurrencias son libres en E salvo aquellas de V. En este caso las V en E se dicen ligadas por el λ antes V.
  3. En expresiones de la forma  (E E′),  las ocurrencias libres son aquellas ocurrencias de E y E′.

Expresiones lambda tales como  λ x. (x y no definen funciones porque las ocurrencias de y están libres. Si la expresión no tiene variables libres, se dice que es cerrada.

Como se permite la repetición del identificador de variables, cada binding tiene una zona de alcance asociada (scope de ahora en adelante) Un ejemplo típico es:  (λx.x(λx.x))x, donde el scope del binding más a la derecha afecta sólo a la x que tiene ahí, la situación del otro binding es análoga, pero no incluye el scope de la primera. Por último la x más a la derecha está libre. Por lo tanto, esa expresión puede reexpresarse así  (λy.y(λz.z))x

α-conversión

La regla de alfa-conversión fue pensada para expresar la idea siguiente: los nombres de las variables ligadas no son importantes. Por ejemplo  λx.x  y  λy.y  son la misma función. Sin embargo, esta regla no es tan simple como parece a primera vista. Hay algunas restricciones que hay que cumplir antes de cambiar el nombre de una variable por otra. Por ejemplo, si reemplazamos x por y en λxy.x, obtenemos λyy.y, que claramente, no es la misma función. Este fenómemo se conoce como captura de variables.

La regla de alfa-conversión establece que si V y W son variables, E es una expresión lambda, y

E[V := W]

representa la expresión E con todas las ocurrencias libres de V en E reemplazadas con W, entonces

λ V. E  ==  λ W. E[V := W]

si W no está libre en E y W no está ligada a un λ donde se haya reemplazado a V. Esta regla nos dice, por ejemplo, que  λ x. (λ xxx  es equivalente a  λ y. (λ xxy.

En un ejemplo de otro tipo, se ve que

for (int i = 0; i < max; i++) { proc (i); }

es equivalente a

for (int j = 0; j < max; j++) { proc (j); }

β-reducción

La regla de beta reducción expresa la idea de la aplicación funcional. Enuncia que

((λ V. E) E′)  ==  E[V := E′]

si todas las ocurrencias de E′ están libres en E[V := E′].

Una expresión de la forma ((λ V. E) E′) es llamada un beta redex. Una lambda expresión que no admite ninguna beta reducción se dice que está en su forma normal. No toda expresión lambda tiene forma normal, pero si existe, es única. Más aún, existe un algoritmo para computar la formal normal: la reducción de orden normal. La ejecución de este algoritmo termina si y sólo si la expresión lambda tiene forma normal. El Teorema de Church-Rosser nos dice que dos expresiones reducen a una misma si y sólo si son equivalentes (salvo por el nombre de sus variables ligadas)

η-conversión

Es la tercer regla, eta conversión, que podría ser añadida a las dos anteriores para formar una nueva relación de equivalencia. La eta conversión expresa la idea de extensionalidad, que en este contexto implica que dos funciones son la misma si y solo si dan el mismo resultado para cualquier argumento. La eta conversión convierte entre  λ x. f x  y  f  siempre que x no aparezca sola en f. Esto puede ser entendido como equivalente a la extensionalidad así:

Si f y g son extensionalmente equivalentes, es decir, si  f a== g a  para cualquier expresión lambda a entonces, en particular tomando a como una variable x que no aparece sola en f ni en g, tenemos que  f x  == g x  y por tanto  λ xf x ==  λ xg x,  y así por eta conversión  f  == g.  Entonces, si aceptamos la eta conversión como válida, resulta que la extensionalidad es válida.

Inversamente, si aceptamos la extensionalidad como válida entonces, dado que por beta reducción de todo y tenemos que  (λ xf xy ==  f y,  resulta que  λ xf x   ==  f;  es decir, descubrimos que la eta conversión es válida.

Conclusiones

El cálculo lambda es computacionalmente equivalente en poder a muchos otros modelos plausibles para el cómputo (máquinas de Turing incluídas); es decir, cualquier cálculo que se pueda lograr en cualesquiera de estos otros modelos se puede expresar en el cálculo lambda y viceversa. Según la tesis de Church-Turing, ambos modelos pueden expresar cualquier cómputo posible.

Quizás parezca sorprendente que el cálculo lambda pueda representar cualquier cómputo concebible usando solamente las nociones simples de abstracción funcional y aplicación basado en la substitución textual simple de términos por variables. Pero aún más notable es que incluso la abstracción no es requerible: la lógica combinatoria es un modelo del cómputo equivalente al cálculo lambda, pero sin la abstracción.

Véase También

Fuentes