fbpx
Wikipedia

Cálculo lambda

En lógica matemática, el cálculo lambda es un sistema formal diseñado para investigar la definición de función, la noción de aplicación de funciones y la recursión. Fue introducido por Alonzo Church y Stephen Kleene en la década de 1930 como parte de sus investigaciones sobre los fundamentos de las matemáticas. Church usó el cálculo lambda en 1936 para resolver el Entscheidungsproblem. Puede ser usado para definir de manera limpia y precisa qué es una "función computable".

El interrogante de si dos expresiones del cálculo lambda son equivalentes no puede ser resuelto por un algoritmo general. Esta fue la primera pregunta, incluso antes que el problema de la parada, cuya indecidibilidad fue probada. El cálculo lambda tiene una gran influencia sobre los lenguajes funcionales, como Lisp, ML y Haskell.

Se puede considerar al cálculo lambda como uno de los lenguajes universales de programación más minimalistas. Consiste en una regla de transformación simple (sustitución de variables) y un esquema simple para definir funciones.

El cálculo lambda es universal porque cualquier función computable puede ser expresada y evaluada a través de él. Por lo tanto, es equivalente a las máquinas de Turing. Sin embargo, el cálculo lambda no hace énfasis en el uso de reglas de transformación y no considera las máquinas reales que pueden implementarlo. Se trata de una propuesta más cercana al software que al hardware.

Este artículo se enfocará sobre el cálculo lambda sin tipos, como fue diseñado originalmente por Church. Desde entonces, algunos cálculo lambda tipados fueron creados.

Historia

Originalmente, Church había tratado de construir un sistema formal completo para modelizar la matemática;[1]​ pero en 1934 Kleene y Rosser publicaron una implementación de la paradoja de Richard.[2]​ Desde ese punto, el cálculo lambda fue usado para estudiar la computabilidad, culminando en la respuesta negativa al problema de la parada. En 1940, Church introdujo el Cálculo lambda simplemente tipado que es computacionalmente menos poderoso, pero lógicamente consistente.[3]

Introducció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. Esto puede parecer difícil de entender, 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 solo 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 solo 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)

o

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

tratar de reducir estas expresiones solo lleva a encontrarse 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, x3,...
  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) Las ligaduras son x,y y z.

La ligadura 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 solo 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ómeno 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 forma normal: la reducción de orden normal. La ejecución de este algoritmo termina si y solo si la expresión lambda tiene forma normal. El teorema de Church-Rosser nos dice que dos expresiones reducen a una misma si y solo si son equivalentes (salvo por el nombre de sus variables ligadas)

η-conversión

Es la tercera regla, esta 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.

Cálculos aritméticos con lambda

Hay varias formas posibles de definir los números naturales en el cálculo lambda, pero el más común son los números de Church, que pueden definirse como sigue:

0:= λ f x. x
1:= λ f x. f x
2:= λ f x. f (f x)
3:= λ f x. f (f (f x))

y así sucesivamente. Instintivamente el número n en el cálculo lambda es una función que toma a otra función f como argumento y devuelve la n-ésima composición de f. Así que, un número de Church es una función de alto nivel -- toma una única función f como parámetro y otra función de parámetro único.

(Véase que en el cálculo original lambda de Church era obligatorio que el parámetro formal de la expresión lambda apareciera al menos una vez en el cuerpo de la función, lo que hace imposible definir el 0.) Dada esta definición de los números de Church, se puede establecer una función de sucesión que dado un número n devuelve n + 1:

SUCC:= λ n f x. f ((n f) x)

La suma se define así:

PLUS:= λ m n f x. n f (m f x)

PLUS puede entenderse como una función que toma dos números naturales como parámetros devolviendo otro; puede verificarse que

PLUS 2 3    and    5

son expresiones lambda equivalentes. La Multiplicación se expresa como

MULT:= λ m n. m (PLUS n) 0,

la idea es que multiplicar m y n es lo mismo que sumar m veces a n. De otra manera:

MULT:= λ m n f. m (n f)

La función Predecesor  PRED n = n - 1  de un entero positivo n es más compleja:

PRED:= λ n f x. ng h. h (g f)) (λ u. x) (λ u. u

o alternativamente

PRED:= λ n. ng k. (g 1) (λ u. PLUS (g k) 1) k) (λ v. 0) 0

Véase que el truco consiste en que (g 1) (λ u. PLUS (g k) 1) k que devuelve k si el valor de g(1) es cero o g(k) + 1 en cualquier otro caso.

Lógica y predicados

Para poder llegar a una definición de booleanos en cálculo lambda, se comienza con su especificación: TRUE, FALSE y ifthenelse deben ser λ-expresiones en forma normal, tal que para todo par de λ-expresiones P y Q

(ifthenelse FALSE P Q) →β Q
(ifthenelse TRUE P Q) →β P

Cualquier par de expresiones que cumplan esto sirve. La solución más simple resulta de fijar ifthenelse como λb.λx.λy. b x y, dejando que todo el trabajo de aplicar los booleanos recaiga sobre TRUE y FALSE, entonces:

(ifthenelse TRUE) →β (λx.λy.x)
(ifthenelse FALSE) →β (λx.λy.y)

Quedando:

TRUE:= λ x y. x
FALSE:= λ x y. y

Los booleanos (como era de esperarse) también son funciones. Es fácil ver que es posible cambiar la λ-expresión ifthenelse para que aplique los parámetros en orden inverso, cambiando la forma de TRUE y FALSE. Por eso, se adapta, por convención, de esta manera (conocida como booleanos de Church). Nótese que FALSE es equivalente al número de Church cero.

Luego, con estas dos definiciones podemos definir algunos operadores lógicos:

AND:= λ p q. p q FALSE
OR:= λ p q. p TRUE q
NOT:= λ p. p FALSE TRUE
IFTHENELSE:= λpab.p a b , siendo "p" una condición booleana (true/false), "a" lo que se devuelve en caso de que se cumpla la condición, "b" lo que se devuelve en caso contrario.
XOR:= λxy.x y FALSE TRUE y

Ahora podemos reducir, por ejemplo:

AND TRUE FALSE
≡ (λ p q. p q FALSE) TRUE FALSE →β TRUE FALSE FALSE
≡ (λ x y. x) FALSE FALSE →β FALSE

y vemos que AND TRUE FALSE es equivalente a FALSE.

Un predicado es una función que devuelve un valor booleano. El predicado más simple es ISZERO el cual nos devuelve TRUE si el número de Church argumento es 0 o FALSE en otro caso.

ISZERO:= λ n. nx. FALSE) TRUE

Por supuesto, esta definición nos sirve solo para los números naturales definidos previamente.

Pares

Un par (2-tupla) puede ser definido en términos de TRUE y FALSE.

CONS:= λfs. λb. b f s
CAR:= λp. p TRUE
CDR:= λp. p FALSE
NIL:= λx.TRUE
NULL:= λp. p (λx y.FALSE)

Una estructura de datos del tipo lista enlazada puede ser definida, tanto como NIL para la lista vacía, o como el CONS de un elemento y de la lista más pequeña en tal caso sea requerido.

Recursión

Recursión es la definición de una función usando la función que se está definiendo. El cálculo lambda no permite esto. Sin embargo, esta noción es un poco confusa. Considere por ejemplo la definición de la función factorial f(n) definida recursivamente por:

f(n) = 1, if n = 0; and n·f(n-1), if n>0.

En el cálculo lambda, no es posible definir funciones que se incluyan a sí mismas. Para sortear esta dificultad, se comienza por definir una función, denominada aquí como g, que toma a una función f como argumento y devuelve otra función que toma n como argumento:

g:= λ f n. (1, if n = 0; and n·f(n-1), if n>0).

La función que devuelve g es o bien la constante 1, o n veces la aplicación de la función f a n-1. Usando el predicado ISZERO, y las definiciones booleanas y algebraicas anteriores, la función g puede ser definida en el cálculo lambda.

Sin embargo, g todavía no es recursiva en sí misma; para usar g para crear la función factorial recursiva, la función pasada a g como f debe tener unas propiedades específicas. A saber, la función pasada como f debe expandirse a la funcióng llamada con un argumento -- y que el argumento debe ser la función que ha sido pasado como f de nuevo.

En otras palabras, f debe expandir a g(f). Esta llamada a g expandirá a la siguiente a la función factorial y calculará otro nivel de recursión. En la expansión la función f aparecerá nuevamente, y nuevamente expandirá a g(f) y continuara la recursión. Este tipo de función, donde f = g(f), es llamada un fixed-point de g, y resulta que puede ser implementado en el cálculo lambda usando lo que es conocido como el paradoxical operator or fixed-point operator y es representado como Y -- el Y combinator:

Y = λ g. (λ x. g (x x)) (λ x. g (x x))

En el cálculo lambda, Y g es un punto fijo de g, debido a que expande a g (Y g). Ahora, para completar nuestra llamada recursiva a la función factorial, simplemente llamaría  g (Y g) n,  donde n es el número del cual queremos calcular el factorial.

Dado, por ejemplo n = 5, esta se expandirá como:

n.(1, si n = 0; y n·((Y g)(n-1)), si n>0)) 5
1, si 5 = 0; y 5·(g(Y g)(5-1)), si 5>0
5·(g(Y g) 4)
5·(λ n. (1, si n = 0; y n·((Y g)(n-1)), si n>0) 4)
5·(1, si 4 = 0; y 4·(g(Y g)(4-1)), si 4>0)
5·(4·(g(Y g) 3))
5·(4·(λ n. (1, si n = 0; y n·((Y g)(n-1)), si n>0) 3))
5·(4·(1, if 3 = 0; y 3·(g(Y g)(3-1)), si 3>0))
5·(4·(3·(g(Y g) 2)))
...

Y así, se va evaluando la estructura del algoritmo de forma recursiva. Cada función recursiva definida puede ser vista como un punto fijo de otra función adecuada, y por lo tanto, utilizando Y, cada función recursiva definida puede expresarse como una expresión lambda. En particular, ahora podemos definir limpiamente la resta, la multiplicación y la comparación de predicado de los números naturales de forma recursiva.

Funciones computables y el cálculo lambda

Una función F: NN de números naturales es una función computable si y solo si existe una expresión lambda f tal que para todo par de x, y in N,  F(x) = y  si y solo si  f x == y,  donde x e y son numerales de Church correspondientes a x e y, respectivamente. Esta solo es una de tantas maneras de definir computabilidad; véase tesis de Church-Turing para una discusión, otras aproximaciones y sus equivalencias.

Indecisión de equivalencia

No hay un algoritmo que tome dos expresiones lambda arbitrarias y produzca TRUE o FALSE dependiendo de si las dos expresiones son o no equivalentes. Este fue históricamente el primer problema para el cual la irresolubilidad pudo ser probada. Por supuesto, de manera previa para hacer esto, la noción de algoritmo tuvo que ser definida de forma clara; Church la definió usando funciones recursivas, la cual se sabe que es equivalente a todas las otras definiciones razonables de esta noción.

La primera prueba de Church reduce el problema de determinar si una expresión lambda dada tiene una forma normal. Una forma normal es una expresión equivalente irreductible. Entonces se asume que este predicado es computable y que puede ser expresado de aquí en adelante en notación de cálculo lambda. Basándose en un trabajo previo de Kleene y construyendo una numeración de Gödel para expresiones lambda, Church construyó una expresión lambda e que seguía la prueba del teorema de incompletitud de Gödel. Si e se aplica a su propio número Gödel, se produce una contradicción.

Cálculo lambda y los lenguajes de programación

Como lo menciona Peter Landin en su libro clásico Correspondencia entre ALGOL 60 y el cálculo lambda de Church, la mayoría de los lenguajes de programación tienen sus raíces en el cálculo lambda, lo que provee los mecanismos básicos para las abstracciones de procedimiento y abstracciones de aplicaciones (subprogramas).

La implementación del cálculo lambda en una computadora involucra tratar a las "funciones" como objetos de primera clase, lo que aumenta la complejidad de su implementación. Un problema particularmente difícil es la implementación de funciones de orden superior, conocido como el problema de Funarg.

Las contrapartes más prominentes del cálculo lambda en programación son los lenguajes de programación funcional, que esencialmente implementa el cálculo aumentado con algunas constantes y tipos de dato.

Los lenguajes funcionales no son los únicos que soportan las funciones como objetos de primera clase. Muchos lenguajes de programación imperativa, como Pascal, hace tiempo que permiten pasar subprogramas como argumentos a otros subprogramas. En C y su derivado C++ el resultado equivalente se obtiene pasando punteros al código de las funciones (subprogramas). Estos mecanismos están limitados a subprogramas escritos explícitamente en el código, y no soportan directamente funciones de alto nivel. Algunos lenguajes imperativos orientados a objetos, tiene notaciones que representan funciones de cualquier orden; tales mecanismos están disponibles en C++, Smalltalk y más recientemente en ("agentes" de ) Eiffel y ("delegados" de) C#. Como ejemplo, la expresión de "agente en línea" de Eiffel

 agent (x: REAL): REAL do Result := x * x end 

denota un objeto correspondiente a la expresión lambda λ x. x*x (con llamada por valor). Puede ser tratada como cualquier otra expresión, por ejemplo, asignarla a una variable o pasada a una rutina. Si el valor de square es el de la expresión de agente anterior, entonces el resultado de aplicar square a un valor (una reducción β) es expresada como square.item ([a]), donde el argumento es pasado como una tupla.

Un ejemplo en Python usa la forma de funciones:

func = lambda x: x * x 

Lo anterior crea una función anónima llamada func que puede ser pasada como parámetros a otras funciones, ser almacenada en variables, etc. Python también puede tratar cualquier otra función creada con la sentencia estándar como un first-class object.

Lo mismo se aplica a la siguiente expresión en Smalltalk:

[ :x | x * x ] 

Este es un objeto de primera clase (clausura de bloque), que puede ser guardado en variables, pasado como argumento, etc.

Un ejemplo similar en C++ (usando la biblioteca Boost.Lambda):

for_each(v.begin(), v.end(), cout << _1 * _1 << endl;); 

Aquí, la función de librería estándar for_each itera sobre todos los miembros del vector (o lista) v, e imprime el cuadrado de cada elemento. La notación _1 es la convención Boost de Lambda para representar el elemento contenedor, representado como x en cualquier otro lado.

Un delegado simple de c# que toma una variable y retorna el cuadrado. Esta variable función puede ser pasada a otros métodos (o delegados de funciones)

// Declare a delegate signature delegate double MathDelegate (double i); // Create an delegate instance MathDelegate f = delegate (double i) { return Math.Pow (i, 2); }; // Passing 'f' function variable to another method, executing, // and returning the result of the function double Execute (MathDelegate func) { return func(100); } 

Estrategias de reducción

El que un término llegue a una forma normal o no, y cuanto trabajo debe realizarse para ello si se puede, depende sustancialmente de la estrategia de reducción utilizada. La distinción entre las estrategias de reducción está relacionada con la distinción en lenguajes de programación funcional entre evaluación estricta y evaluación perezosa.

Reducciones beta completas
Cualquier redex puede ser reducida en cualquier momento. Esto simboliza la falta de una estrategia particular.
Orden aplicativo
Primero se reducen las redexes más profundas y más situadas a la derecha. Intuitivamente, esto significa que los argumentos de una función son siempre reducidos antes que la propia función. El orden aplicativo intenta siempre aplicar funciones a formas normales, incluso cuando esto no es posible.
La mayoría de lenguajes de programación (incluyendo Lisp, ML y otros lenguajes imperativos como C y Java) se describen como "estrictos", lo que significa que la aplicación de funciones a términos no normalizables es no normalizable. Esto se logra utilizando una reducción por orden aplicativo (call by value, o llamada por valor, aunque usualmente llamada evaluación estricta).
Orden normal
La redex más superficial y más a la izquierda se evalúa primero. Por tanto, siempre que sea posible, los argumentos de una abstracción son sustituidos en su cuerpo antes de que los argumentos sean reducidos.
Llamada por nombre
Como el orden normal, pero no se realizan reducciones dentro de las abstracciones. Por ejemplo: λx.(λx.x)x estaría en forma normal bajo esta estrategia, aunque contiene la redex (λx.x)x.
Llamada por valor
Solo las redexes más superficiales son reducidas: una redex solo se reduce cuando su expresión derecha ha sido reducida a un valor (una variable o una abstracción lambda).
Llamada por necesidad
Como el orden normal, pero las aplicaciones de funciones que duplicarían argumentos nombran el argumento en su lugar, que es entonces reducido solo "cuando se le necesita". A menudo llamado evaluación perezosa, su implementación de "nombre" suele lograrse con un puntero, con la redex representada como un thunk.

El orden aplicativo no es una estrategia de normalización. El ejemplo más típico es el siguiente: se define Q = ωω donde ω = λx.xx. Esta expresión solo contiene una redex (la expresión completa), la cual resulta al ser reducida otra vez en Q. Como es la única reducción posible, Q no tiene forma normal bajo ninguna estrategia de reducción. Utilizando orden aplicativo, la expresión KIΩ = (λx.λy.x) (λx.x)Ω es reducida reduciendo primero Q, pero como no tiene forma normal, esta estrategia fracasa a la hora de encontrar una forma normal para KIQ.

En contraposición, el orden normal siempre encuentra la forma normal si esta existe. En el ejemplo anterior, KIQ es reducido bajo orden normal a I, una forma normal. Uno de los inconvenientes es que las redexes en los argumentos pueden ser copiadas, resultando en trabajo duplicado. En ese caso, el orden aplicativo se encuentra en ventaja, porque nunca sustituye argumentos que contengan redexes, y el trabajo es realizado una única vez.

La mayoría de lenguajes de programación funcionales puros (sobre todo Miranda y sus descendientes, incluyendo Haskell) utilizan evaluación perezosa, que es esencialmente idéntica a la llamada por necesidad. Esta es similar a la reducción por orden normal, pero evita la duplicación de trabajo mediante la representación indirecta de los términos repetidos, abstraída de su posición real y accedida de forma indirecta (y por tanto, varias posiciones pueden compartir el mismo término).

Concurrencia y paralelismo

La propiedad Church-Rosser del cálculo lambda significa que la evaluación (reducción-β) puede ser llevada a cabo en "cualquier orden", incluso al mismo tiempo (de hecho, el cálculo lambda es de transparencia referencial). Aunque esto significa que el cálculo lambda puede crear un modelo de diversas estrategias de evaluación no deterministas, no ofrece ninguna noción acerca de la computación paralela, ni expresa ningún lenguaje de programación simultáneo (o concurrente). Procesadores de cálculo tales como el CSP, CSS, el Cálculo-π y el Cálculo ambiente han sido diseñados para tales propósitos.

A pesar de que el cálculo lambda no determinista es capaz de expresar cualquier "función" parcial recursiva, no es capaz de expresar cualquier "computación". Por ejemplo, no es capaz de expresar no-determinismos infinitos (como cualquier expresión lamba no determinista que termine; terminará en un número finito de expresiones). Sin embargo, hay programas concurrentes que garantizan la interrupción de ese término en un número infinito de estados [Clinger 1981, Hewitt 2006].

Reducción óptima

Lévy define en su publicación de 1988 "Sharing in the Evaluation of lambda Expressions" la noción de compartir óptimamente, de forma que no se duplique el trabajo. Por ejemplo, realizar una reducción beta en orden normal sobre x.xx) (II) la reduce a II (II). El argumento II es duplicado por la aplicación al primer término lambda. Si la reducción se realizó en orden aplicativo primero, se ahorra trabajo porque no se duplican esfuerzos: (λx.xx) (II) se reduce a (λx.xx) I. Por otra parte, emplear orden aplicativo puede resultar en reducciones redundantes o incluso nunca reducirse a una forma normal. Por ejemplo, realizar una reducción beta en orden normal en (λf.f I) (λy.(λx.xx) (y I)) resulta en (λy.(λx.xx) (y I)) I, (λx.xx) (II), que puede ser realizado sin duplicar esfuerzos. Hacer lo mismo pero en orden aplicativo resulta en (λf.f I) (λy.y I (y I)), (λy.y I (y I)) I, I I (I I), por lo que ahora el trabajo se duplica.

Lévy muestra la existencia de términos lambda donde no existe una secuencia de reducciones que las reduzca sin duplicar el trabajo a realizar. El siguiente término lambda es un ejemplo de estos términos:

((λg.(g(g(λx.x)))) (λh.((λf.(f(f(λz.z)))) (λw.(h(w(λy.y)))))))

Está compuesto de tres términos similares, x=((λg. ... ) (λh.y)), y=((λf. ...) (λw.z) ) y z=λw.(h(w(λy.y))). Solo hay dos reducciones beta posibles, sobre x y sobre y. Reducir el término x externo primero resulta en términos duplicados (el término interno y el término y), y cada copia debe ser reducida; pero reducir el término y primero duplica su argumento z, que causará que se duplique el trabajo cuando se conozcan los valores de h y w. Curiosamente, dicho término se reduce a la función identidad (λy.y), y se construye realizando encapsulaciones sucesivas.

La noción precisa de trabajo duplicado se basa en darse cuenta de que tras hacerse la primera reducción a I I, el valor de otro I I puede determinarse, porque tienen la misma estructura (y tienen de hecho el mismo valor), y resultan de un ancestro común. A dichas estructuras similares se les puede asignar una etiqueta que puede ser rastreada durante las reducciones. Si un nombre es asignado a la redex que produce todos los términos II resultantes, después todas las ocurrencias duplicadas de II pueden ser localizadas y reducidas de una vez. Sin embargo, no es obvio si una redex producirá el término II. Identificar las estructuras que son similares en partes diferentes de un término lambda puede requerir de algoritmos complejos y puede conllevar incluso una complejidad igual al historial de la reducción misma.

Mientras Lévy define la noción de compartir óptimamente, no proporciona un algoritmo para hacerlo. En la publicación de Vincent van Oostrom, Kees-Jan van de Looij y Marijn Zwitserlood Lambdascope: Another optimal implementation of the lambda-calculus, se proporciona tal algoritmo transformando términos lambda en redes de interacción, que después son reducidas. En términos generales, la reducción resultante es óptima porque cada término que tuviese la misma etiqueta según el trabajo de Lévy serían el mismo grafo en la red de interacción. En la publicación, mencionan que su prototipo de Lambdascope rinde de forma similar a la versión optimizada de la implementación de referencia de la BOHM.

Semántica

El hecho de que los términos del cálculo lambda puedan actuar como funciones sobre otros términos, o incluso sobre sí mismos, llevó a cuestionarse la semántica del cálculo lambda. ¿Se le puede asignar un significado a los términos del cálculo lambda? La semántica natural era encontrar un conjunto D isomórfico al espacio de funciones D → D, de funciones de sí mismo. Sin embargo, no puede existir tal D que no sea trivial, por restricciones de cardinalidad, porque el conjunto de todas las funciones de D a D tiene mayor cardinalidad que D a menos que sea un conjunto unitario

En 1970, Dana Scott mostró que, si solo se consideran funciones continuas, un conjunto o dominio D con las propiedades necesarias se puede encontrar, proporcionando por tanto un modelo para el cálculo lambda.

Este trabajo también sentó las bases para la semántica denotacional de los lenguajes de programación

Referencias

  1. A. Church, "A set of postulates for the foundation of logic", Annals of Mathematics, Series 2, 33:346-366 (1932).
  2. Kleene, S. C. & Rosser, J. B. (1935). «The inconsistency of certain formal logics». Annals of Mathematics 36 (3): 630-636. doi:10.2307/1968646. 
  3. Church, A. «A Formulation of the Simple Theory of Types». Journal of Symbolic Logic 5: 1940. 
  • Abelson, Harold & Gerald Jay Sussman. Structure and Interpretation of Computer Programs. [[The MIT Press]]. ISBN 0-262-51087-1.
  • Barendregt, Henk, , North-Holland (1984), is the comprehensive reference on the (untyped) lambda calculus; see also the paper Introduction to Lambda Calculus.
  • Barendregt, Henk, The Type Free Lambda Calculus pp1091-1132 of Handbook of Mathematical Logic, North-Holland (1977) ISBN 0-7204-2285-X
  • Church, Alonzo, An unsolvable problem of elementary number theory, American Journal of Mathematics, 58 (1936), pp. 345-363. This paper contains the proof that the equivalence of lambda expressions is in general not decidable.
  • Clinger, William, Foundations of Actor Semantics. MIT Mathematics Doctoral Dissertation, June 1981.
  • Punit, Gupta, Amit & Ashutosh Agte, Untyped lambda-calculus, alpha-, beta- and eta- reductions and recursion
  • Henz, Martin, The Lambda Calculus. Formally correct development of the Lambda calculus.
  • Hewitt, Carl, What is Commitment? Physical, Organizational, and Social COIN@AAMAS. April 27, 2006.
  • Kleene, Stephen, A theory of positive integers in formal logic, American Journal of Mathematics, 57 (1935), pp. 153-173 and 219-244. Contains the lambda calculus definitions of several familiar functions.
  • Landin, Peter, A Correspondence Between ALGOL 60 and Church's Lambda-Notation, Communications of the ACM, vol. 8, no. 2 (1965), pages 89-101. Available from the ACM site. A classic paper highlighting the importance of lambda-calculus as a basis for programming languages.
  • Larson, Jim, . A gentle introduction for programmers.

Some parts of this article are based on material from FOLDOC, used with permission.

  • Miguel Ángel Jiménez Santana,

Enlaces externos

  • L. Allison, Algunos ejemplos ejecutables de cálculo-λ (en inglés)
  • Chris Barker, Lambda tutorial Some executable (Javascript) Ejemplos simples, con anotaciones. (en inglés)
  • Georg P. Loczewski, The Lambda Calculus and A++
  • Raúl Rojas, A Tutorial Introduction to the Lambda Calculus -(PDF)
  • David C. Keenan,
  • Bret Victor, Alligator Eggs: A Puzzle Game Based on Lambda Calculus
  • Miguel Ángel Jiménez Santana,
  • Camilo Chacón Sartori, Introducción al cálculo lambda usando Racket (español)
  •   Datos: Q242028
  •   Multimedia: Lambda calculus

cálculo, lambda, lógica, matemática, cálculo, lambda, sistema, formal, diseñado, para, investigar, definición, función, noción, aplicación, funciones, recursión, introducido, alonzo, church, stephen, kleene, década, 1930, como, parte, investigaciones, sobre, f. En logica matematica el calculo lambda es un sistema formal disenado para investigar la definicion de funcion la nocion de aplicacion de funciones y la recursion Fue introducido por Alonzo Church y Stephen Kleene en la decada de 1930 como parte de sus investigaciones sobre los fundamentos de las matematicas Church uso el calculo lambda en 1936 para resolver el Entscheidungsproblem Puede ser usado para definir de manera limpia y precisa que es una funcion computable El interrogante de si dos expresiones del calculo lambda son equivalentes no puede ser resuelto por un algoritmo general Esta fue la primera pregunta incluso antes que el problema de la parada cuya indecidibilidad fue probada El calculo lambda tiene una gran influencia sobre los lenguajes funcionales como Lisp ML y Haskell Se puede considerar al calculo lambda como uno de los lenguajes universales de programacion mas minimalistas Consiste en una regla de transformacion simple sustitucion de variables y un esquema simple para definir funciones El calculo lambda es universal porque cualquier funcion computable puede ser expresada y evaluada a traves de el Por lo tanto es equivalente a las maquinas de Turing Sin embargo el calculo lambda no hace enfasis en el uso de reglas de transformacion y no considera las maquinas reales que pueden implementarlo Se trata de una propuesta mas cercana al software que al hardware Este articulo se enfocara sobre el calculo lambda sin tipos como fue disenado originalmente por Church Desde entonces algunos calculo lambda tipados fueron creados Indice 1 Historia 2 Introduccion informal 3 Definicion formal 3 1 Sintaxis 3 2 Variables libres y ligadas 3 3 a conversion 3 4 b reduccion 3 5 h conversion 4 Calculos aritmeticos con lambda 5 Logica y predicados 6 Pares 7 Recursion 8 Funciones computables y el calculo lambda 9 Indecision de equivalencia 10 Calculo lambda y los lenguajes de programacion 11 Estrategias de reduccion 12 Concurrencia y paralelismo 13 Reduccion optima 14 Semantica 15 Referencias 16 Enlaces externosHistoria EditarOriginalmente Church habia tratado de construir un sistema formal completo para modelizar la matematica 1 pero en 1934 Kleene y Rosser publicaron una implementacion de la paradoja de Richard 2 Desde ese punto el calculo lambda fue usado para estudiar la computabilidad culminando en la respuesta negativa al problema de la parada En 1940 Church introdujo el Calculo lambda simplemente tipado que es computacionalmente menos poderoso pero logicamente consistente 3 Introduccion informal EditarConsiderese las siguientes dos funciones Por un lado la funcion identidad I x x que toma un unico argumento x e inmediatamente devuelve x Por otro lado la funcion 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 utiles acerca de varias ideas fundamentales del calculo lambda La primera observacion es que las funciones no necesitan ser explicitamente nombradas Esto es la funcion S x y x y puede ser reescrita como una funcion anonima 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 anonima como x x que se lee el argumento x se mapea a si mismo La segunda observacion es que el nombre que se asigne a los argumentos de la funcion es generalmente irrelevante Esto es x x e y y expresan la misma funcion la funcion identidad Del mismo modo x y x y y u v u v expresan la misma funcion la funcion suma Una tercera observacion es que toda funcion que requiere dos argumentos como por ejemplo la funcion suma puede ser reescrita como una funcion que acepta un unico argumento pero que devuelve otra funcion la cual a su vez acepta un unico argumento Por ejemplo x y x y puede ser reescrita como x y x y Esta transformacion se conoce como currificacion y puede generalizarse para funciones que aceptan cualquier numero de argumentos Esto puede parecer dificil de entender pero se entiende mejor mediante un ejemplo Considerese la funcion suma no currificada x y x yAl tomar a los numeros 2 y 3 como argumentos se obtiene 2 3Lo cual es igual a 5 Considerese ahora la version currificada de la funcion x y x y Si se toma al numero 2 como argumento se obtiene la funcion y 2 yY tomando luego al numero 3 como argumento se obtiene 2 3Lo cual es igual a 5 De modo que la version currificada devuelve el mismo resultado que la version no currificada En el calculo lambda todas las expresiones representan funciones anonimas de un solo argumento Una cuarta observacion es que una funcion puede aceptar como argumento a otra funcion siempre y cuando esta otra funcion tenga ella misma un solo argumento Por ejemplo la funcion identidad puede aceptar como argumento a la funcion suma currificada Es decir se toma a la funcion x y x y y se la pone como argumento en z z El resultado sera obviamente x z x z igual a la x y x y pues la funcion identidad siempre devuelve lo mismo que se le da En el calculo lambda las funciones estan definidas por expresiones lambda que dicen que se hace con su argumento Por ejemplo la funcion sumar 2 f x x 2 se expresa en calculo lambda asi l x x 2 o equivalentemente l y y 2 ya que el nombre de su argumento no es importante Y el numero f 3 seria escrito como l x x 2 3 La aplicacion de funciones es asociativa a izquierda f x y f x y Considerando la funcion que aplica una funcion al numero 3 l f f 3 podemos pasarle sumar 2 quedando asi l f f 3 l x x 2 Las tres expresiones l f f 3 l x x 2 l x x 2 3 y 3 2 son equivalentes No todas las expresiones lambda pueden ser reducidas a un valor definido Considerese la siguiente l x x x l x x x o l x x x x l x x x x tratar de reducir estas expresiones solo lleva a encontrarse con la misma expresion o algo mas complejo l x x x es conocido como w combinador l x x x l x x x se conoce como W l x x x x l x x x x como W2 etc Definicion formal EditarSintaxis Editar En el calculo lambda una expresion o termino se define recursivamente a traves de las siguientes reglas de formacion Toda variable es un termino x y z u v w x1 x2 x3 Si t es un termino y x es una variable entonces lx t es un termino llamado una abstraccion lambda Si t y s son terminos entonces ts es un termino llamado una aplicacion lambda Nada mas es un termino Segun estas reglas de formacion las siguientes cadenas de caracteres son terminos x xy xz y x lx x lx x y lz lx y x lz z z Por convencion se suelen omitir los parentesis externos ya que no cumplen ninguna funcion de desambiguacion Por ejemplo se escribe lz z z en vez de lz z z y se escribe x y zx en vez de x y zx Ademas se suele adoptar la convencion de que la aplicacion de funciones es asociativa hacia la izquierda Esto quiere decir por ejemplo que xyzz debe entenderse como xy z z y que lz z yzx debe entenderse como lz z y z x Las primeras dos reglas generan funciones mientras que la ultima describe la aplicacion de una funcion a un argumento Una abstraccion lambda lx t representa una funcion anonima que toma un unico argumento y se dice que el signo l liga la variable x en el termino t En cambio una aplicacion lambda ts representa la aplicacion de un argumento s a una funcion t Por ejemplo lx x representa la funcion identidad x x y lx x y representa la funcion identidad aplicada a y Luego lx y representa la funcion constante x y que develve y sin importar que argumento se le de Las expresiones lambda no son muy interesantes por si mismas Lo que las hace interesantes son las muchas nociones de equivalencia y reduccion que pueden ser definidas sobre ellas Variables libres y ligadas Editar Las apariciones ocurrencias de variables en una expresion son de tres tipos Ocurrencias de ligadura binders Ocurrencias ligadas bound occurrences Ocurrencias libres free occurrences Las variables de ligadura son aquellas que estan entre el l y el punto Por ejemplo siendo E una expresion lambda l x y z E Las ligaduras son x y y z La ligadura de ocurrencias de una variable esta definido recursivamente sobre la estructura de las expresiones lambda de esta manera En expresiones de la forma V donde V es una variable V es una ocurrencia libre En expresiones de la forma l V E las ocurrencias son libres en E salvo aquellas de V En este caso las V en E se dicen ligadas por el l antes V En expresiones de la forma E E las ocurrencias libres son aquellas ocurrencias de E y E Expresiones lambda tales como l x x y no definen funciones porque las ocurrencias de y estan libres Si la expresion no tiene variables libres se dice que es cerrada Como se permite la repeticion del identificador de variables cada binding tiene una zona de alcance asociada scope de ahora en adelante Un ejemplo tipico es lx x lx x x donde el scope del binding mas a la derecha afecta solo a la x que tiene ahi la situacion del otro binding es analoga pero no incluye el scope de la primera Por ultimo la x mas a la derecha esta libre Por lo tanto esa expresion puede reexpresarse asi ly y lz z x a conversion Editar La regla de alfa conversion fue pensada para expresar la idea siguiente los nombres de las variables ligadas no son importantes Por ejemplo lx x y ly y son la misma funcion 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 lx ly x obtenemos ly ly y que claramente no es la misma funcion Este fenomeno se conoce como captura de variables La regla de alfa conversion establece que si V y W son variables E es una expresion lambda yE V W representa la expresion E con todas las ocurrencias libres de V en E reemplazadas con W entonces l V E l W E V W si W no esta libre en E y W no esta ligada a un l donde se haya reemplazado a V Esta regla nos dice por ejemplo que l x l x x x es equivalente a l y l x x y En un ejemplo de otro tipo se ve quefor int i 0 i lt max i proc i es equivalente afor int j 0 j lt max j proc j b reduccion Editar La regla de beta reduccion expresa la idea de la aplicacion funcional Enuncia que l V E E E V E si todas las ocurrencias de E estan libres en E V E Una expresion de la forma l V E E es llamada un beta redex Una lambda expresion que no admite ninguna beta reduccion se dice que esta en su forma normal No toda expresion lambda tiene forma normal pero si existe es unica Mas aun existe un algoritmo para computar la forma normal la reduccion de orden normal La ejecucion de este algoritmo termina si y solo si la expresion lambda tiene forma normal El teorema de Church Rosser nos dice que dos expresiones reducen a una misma si y solo si son equivalentes salvo por el nombre de sus variables ligadas h conversion Editar Es la tercera regla esta conversion que podria ser anadida a las dos anteriores para formar una nueva relacion de equivalencia La eta conversion 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 conversion convierte entre l x f x y f siempre que x no aparezca sola en f Esto puede ser entendido como equivalente a la extensionalidad asi Si f y g son extensionalmente equivalentes es decir si f a g a para cualquier expresion 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 l x f x l x g x y asi por eta conversion f g Entonces si aceptamos la eta conversion como valida resulta que la extensionalidad es valida Inversamente si aceptamos la extensionalidad como valida entonces dado que por beta reduccion de todo y tenemos que l x f x y f y resulta que l x f x f es decir descubrimos que la eta conversion es valida Calculos aritmeticos con lambda EditarHay varias formas posibles de definir los numeros naturales en el calculo lambda pero el mas comun son los numeros de Church que pueden definirse como sigue 0 l f x x 1 l f x f x 2 l f x f f x 3 l f x f f f x y asi sucesivamente Instintivamente el numero n en el calculo lambda es una funcion que toma a otra funcion f como argumento y devuelve la n esima composicion de f Asi que un numero de Church es una funcion de alto nivel toma una unica funcion f como parametro y otra funcion de parametro unico Vease que en el calculo original lambda de Church era obligatorio que el parametro formal de la expresion lambda apareciera al menos una vez en el cuerpo de la funcion lo que hace imposible definir el 0 Dada esta definicion de los numeros de Church se puede establecer una funcion de sucesion que dado un numero n devuelve n 1 SUCC l n f x f n f x La suma se define asi PLUS l m n f x n f m f x PLUS puede entenderse como una funcion que toma dos numeros naturales como parametros devolviendo otro puede verificarse que PLUS 2 3 and 5son expresiones lambda equivalentes La Multiplicacion se expresa como MULT l m n m PLUS n 0 la idea es que multiplicar m y n es lo mismo que sumar m veces a n De otra manera MULT l m n f m n f La funcion Predecesor PRED n n 1 de un entero positivo n es mas compleja PRED l n f x n l g h h g f l u x l u u o alternativamente PRED l n n l g k g 1 l u PLUS g k 1 k l v 0 0Vease que el truco consiste en que g 1 l u PLUS g k 1 k que devuelve k si el valor de g 1 es cero o g k 1 en cualquier otro caso Logica y predicados EditarPara poder llegar a una definicion de booleanos en calculo lambda se comienza con su especificacion TRUE FALSE y ifthenelse deben ser l expresiones en forma normal tal que para todo par de l expresiones P y Q ifthenelse FALSE P Q b Q ifthenelse TRUE P Q b PCualquier par de expresiones que cumplan esto sirve La solucion mas simple resulta de fijar ifthenelse como lb lx ly b x y dejando que todo el trabajo de aplicar los booleanos recaiga sobre TRUE y FALSE entonces ifthenelse TRUE b lx ly x ifthenelse FALSE b lx ly y Quedando TRUE l x y x FALSE l x y yLos booleanos como era de esperarse tambien son funciones Es facil ver que es posible cambiar la l expresion ifthenelse para que aplique los parametros en orden inverso cambiando la forma de TRUE y FALSE Por eso se adapta por convencion de esta manera conocida como booleanos de Church Notese que FALSE es equivalente al numero de Church cero Luego con estas dos definiciones podemos definir algunos operadores logicos AND l p q p q FALSE OR l p q p TRUE q NOT l p p FALSE TRUE IFTHENELSE lp la lb p a b siendo p una condicion booleana true false a lo que se devuelve en caso de que se cumpla la condicion b lo que se devuelve en caso contrario XOR lx ly x y FALSE TRUE yAhora podemos reducir por ejemplo AND TRUE FALSE l p q p q FALSE TRUE FALSE b TRUE FALSE FALSE l x y x FALSE FALSE b FALSE dd y vemos que AND TRUE FALSE es equivalente a FALSE Un predicado es una funcion que devuelve un valor booleano El predicado mas simple es ISZERO el cual nos devuelve TRUE si el numero de Church argumento es 0 o FALSE en otro caso ISZERO l n n l x FALSE TRUEPor supuesto esta definicion nos sirve solo para los numeros naturales definidos previamente Pares EditarUn par 2 tupla puede ser definido en terminos de TRUE y FALSE CONS lf ls lb b f s CAR lp p TRUE CDR lp p FALSE NIL lx TRUE NULL lp p lx y FALSE Una estructura de datos del tipo lista enlazada puede ser definida tanto como NIL para la lista vacia o como el CONS de un elemento y de la lista mas pequena en tal caso sea requerido Recursion EditarRecursion es la definicion de una funcion usando la funcion que se esta definiendo El calculo lambda no permite esto Sin embargo esta nocion es un poco confusa Considere por ejemplo la definicion de la funcion factorial f n definida recursivamente por f n 1 if n 0 and n f n 1 if n gt 0 En el calculo lambda no es posible definir funciones que se incluyan a si mismas Para sortear esta dificultad se comienza por definir una funcion denominada aqui como g que toma a una funcion f como argumento y devuelve otra funcion que toma n como argumento g l f n 1 if n 0 and n f n 1 if n gt 0 La funcion que devuelve g es o bien la constante 1 o n veces la aplicacion de la funcion f a n 1 Usando el predicado ISZERO y las definiciones booleanas y algebraicas anteriores la funcion g puede ser definida en el calculo lambda Sin embargo g todavia no es recursiva en si misma para usar g para crear la funcion factorial recursiva la funcion pasada a g como f debe tener unas propiedades especificas A saber la funcion pasada como f debe expandirse a la funciong llamada con un argumento y que el argumento debe ser la funcion que ha sido pasado como f de nuevo En otras palabras f debe expandir a g f Esta llamada a g expandira a la siguiente a la funcion factorial y calculara otro nivel de recursion En la expansion la funcion f aparecera nuevamente y nuevamente expandira a g f y continuara la recursion Este tipo de funcion donde f g f es llamada un fixed point de g y resulta que puede ser implementado en el calculo lambda usando lo que es conocido como el paradoxical operator or fixed point operator y es representado como Y el Y combinator Y l g l x g x x l x g x x En el calculo lambda Y g es un punto fijo de g debido a que expande a g Y g Ahora para completar nuestra llamada recursiva a la funcion factorial simplemente llamaria g Y g n donde n es el numero del cual queremos calcular el factorial Dado por ejemplo n 5 esta se expandira como l n 1 si n 0 y n Y g n 1 si n gt 0 5 1 si 5 0 y 5 g Y g 5 1 si 5 gt 0 5 g Y g 4 5 l n 1 si n 0 y n Y g n 1 si n gt 0 4 5 1 si 4 0 y 4 g Y g 4 1 si 4 gt 0 5 4 g Y g 3 5 4 l n 1 si n 0 y n Y g n 1 si n gt 0 3 5 4 1 if 3 0 y 3 g Y g 3 1 si 3 gt 0 5 4 3 g Y g 2 Y asi se va evaluando la estructura del algoritmo de forma recursiva Cada funcion recursiva definida puede ser vista como un punto fijo de otra funcion adecuada y por lo tanto utilizando Y cada funcion recursiva definida puede expresarse como una expresion lambda En particular ahora podemos definir limpiamente la resta la multiplicacion y la comparacion de predicado de los numeros naturales de forma recursiva Funciones computables y el calculo lambda EditarUna funcion F N N de numeros naturales es una funcion computable si y solo si existe una expresion lambda f tal que para todo par de x y in N F x y si y solo si f x y donde x e y son numerales de Church correspondientes a x e y respectivamente Esta solo es una de tantas maneras de definir computabilidad vease tesis de Church Turing para una discusion otras aproximaciones y sus equivalencias Indecision de equivalencia EditarNo hay un algoritmo que tome dos expresiones lambda arbitrarias y produzca TRUE o FALSE dependiendo de si las dos expresiones son o no equivalentes Este fue historicamente el primer problema para el cual la irresolubilidad pudo ser probada Por supuesto de manera previa para hacer esto la nocion de algoritmo tuvo que ser definida de forma clara Church la definio usando funciones recursivas la cual se sabe que es equivalente a todas las otras definiciones razonables de esta nocion La primera prueba de Church reduce el problema de determinar si una expresion lambda dada tiene una forma normal Una forma normal es una expresion equivalente irreductible Entonces se asume que este predicado es computable y que puede ser expresado de aqui en adelante en notacion de calculo lambda Basandose en un trabajo previo de Kleene y construyendo una numeracion de Godel para expresiones lambda Church construyo una expresion lambda e que seguia la prueba del teorema de incompletitud de Godel Si e se aplica a su propio numero Godel se produce una contradiccion Calculo lambda y los lenguajes de programacion EditarComo lo menciona Peter Landin en su libro clasico Correspondencia entre ALGOL 60 y el calculo lambda de Church la mayoria de los lenguajes de programacion tienen sus raices en el calculo lambda lo que provee los mecanismos basicos para las abstracciones de procedimiento y abstracciones de aplicaciones subprogramas La implementacion del calculo lambda en una computadora involucra tratar a las funciones como objetos de primera clase lo que aumenta la complejidad de su implementacion Un problema particularmente dificil es la implementacion de funciones de orden superior conocido como el problema de Funarg Las contrapartes mas prominentes del calculo lambda en programacion son los lenguajes de programacion funcional que esencialmente implementa el calculo aumentado con algunas constantes y tipos de dato Los lenguajes funcionales no son los unicos que soportan las funciones como objetos de primera clase Muchos lenguajes de programacion imperativa como Pascal hace tiempo que permiten pasar subprogramas como argumentos a otros subprogramas En C y su derivado C el resultado equivalente se obtiene pasando punteros al codigo de las funciones subprogramas Estos mecanismos estan limitados a subprogramas escritos explicitamente en el codigo y no soportan directamente funciones de alto nivel Algunos lenguajes imperativos orientados a objetos tiene notaciones que representan funciones de cualquier orden tales mecanismos estan disponibles en C Smalltalk y mas recientemente en agentes de Eiffel y delegados de C Como ejemplo la expresion de agente en linea de Eiffel agent x REAL REAL do Result x x end denota un objeto correspondiente a la expresion lambda l x x x con llamada por valor Puede ser tratada como cualquier otra expresion por ejemplo asignarla a una variable o pasada a una rutina Si el valor de square es el de la expresion de agente anterior entonces el resultado de aplicar square a un valor una reduccion b es expresada como square item a donde el argumento es pasado como una tupla Un ejemplo en Python usa la forma lambda de funciones func lambda x x x Lo anterior crea una funcion anonima llamada func que puede ser pasada como parametros a otras funciones ser almacenada en variables etc Python tambien puede tratar cualquier otra funcion creada con la sentencia estandar def como un first class object Lo mismo se aplica a la siguiente expresion en Smalltalk x x x Este es un objeto de primera clase clausura de bloque que puede ser guardado en variables pasado como argumento etc Un ejemplo similar en C usando la biblioteca Boost Lambda for each v begin v end cout lt lt 1 1 lt lt endl Aqui la funcion de libreria estandar for each itera sobre todos los miembros del vector o lista v e imprime el cuadrado de cada elemento La notacion 1 es la convencion Boost de Lambda para representar el elemento contenedor representado como x en cualquier otro lado Un delegado simple de c que toma una variable y retorna el cuadrado Esta variable funcion puede ser pasada a otros metodos o delegados de funciones Declare a delegate signature delegate double MathDelegate double i Create an delegate instance MathDelegate f delegate double i return Math Pow i 2 Passing f function variable to another method executing and returning the result of the function double Execute MathDelegate func return func 100 Estrategias de reduccion EditarEl que un termino llegue a una forma normal o no y cuanto trabajo debe realizarse para ello si se puede depende sustancialmente de la estrategia de reduccion utilizada La distincion entre las estrategias de reduccion esta relacionada con la distincion en lenguajes de programacion funcional entre evaluacion estricta y evaluacion perezosa Reducciones beta completas Cualquier redex puede ser reducida en cualquier momento Esto simboliza la falta de una estrategia particular Orden aplicativo Primero se reducen las redexes mas profundas y mas situadas a la derecha Intuitivamente esto significa que los argumentos de una funcion son siempre reducidos antes que la propia funcion El orden aplicativo intenta siempre aplicar funciones a formas normales incluso cuando esto no es posible La mayoria de lenguajes de programacion incluyendo Lisp ML y otros lenguajes imperativos como C y Java se describen como estrictos lo que significa que la aplicacion de funciones a terminos no normalizables es no normalizable Esto se logra utilizando una reduccion por orden aplicativo call by value o llamada por valor aunque usualmente llamada evaluacion estricta Orden normal La redex mas superficial y mas a la izquierda se evalua primero Por tanto siempre que sea posible los argumentos de una abstraccion son sustituidos en su cuerpo antes de que los argumentos sean reducidos Llamada por nombre Como el orden normal pero no se realizan reducciones dentro de las abstracciones Por ejemplo lx lx x x estaria en forma normal bajo esta estrategia aunque contiene la redex lx x x Llamada por valor Solo las redexes mas superficiales son reducidas una redex solo se reduce cuando su expresion derecha ha sido reducida a un valor una variable o una abstraccion lambda Llamada por necesidad Como el orden normal pero las aplicaciones de funciones que duplicarian argumentos nombran el argumento en su lugar que es entonces reducido solo cuando se le necesita A menudo llamado evaluacion perezosa su implementacion de nombre suele lograrse con un puntero con la redex representada como un thunk El orden aplicativo no es una estrategia de normalizacion El ejemplo mas tipico es el siguiente se define Q ww donde w lx xx Esta expresion solo contiene una redex la expresion completa la cual resulta al ser reducida otra vez en Q Como es la unica reduccion posible Q no tiene forma normal bajo ninguna estrategia de reduccion Utilizando orden aplicativo la expresion KIW lx ly x lx x W es reducida reduciendo primero Q pero como no tiene forma normal esta estrategia fracasa a la hora de encontrar una forma normal para KIQ En contraposicion el orden normal siempre encuentra la forma normal si esta existe En el ejemplo anterior KIQ es reducido bajo orden normal a I una forma normal Uno de los inconvenientes es que las redexes en los argumentos pueden ser copiadas resultando en trabajo duplicado En ese caso el orden aplicativo se encuentra en ventaja porque nunca sustituye argumentos que contengan redexes y el trabajo es realizado una unica vez La mayoria de lenguajes de programacion funcionales puros sobre todo Miranda y sus descendientes incluyendo Haskell utilizan evaluacion perezosa que es esencialmente identica a la llamada por necesidad Esta es similar a la reduccion por orden normal pero evita la duplicacion de trabajo mediante la representacion indirecta de los terminos repetidos abstraida de su posicion real y accedida de forma indirecta y por tanto varias posiciones pueden compartir el mismo termino Concurrencia y paralelismo EditarLa propiedad Church Rosser del calculo lambda significa que la evaluacion reduccion b puede ser llevada a cabo en cualquier orden incluso al mismo tiempo de hecho el calculo lambda es de transparencia referencial Aunque esto significa que el calculo lambda puede crear un modelo de diversas estrategias de evaluacion no deterministas no ofrece ninguna nocion acerca de la computacion paralela ni expresa ningun lenguaje de programacion simultaneo o concurrente Procesadores de calculo tales como el CSP CSS el Calculo p y el Calculo ambiente han sido disenados para tales propositos A pesar de que el calculo lambda no determinista es capaz de expresar cualquier funcion parcial recursiva no es capaz de expresar cualquier computacion Por ejemplo no es capaz de expresar no determinismos infinitos como cualquier expresion lamba no determinista que termine terminara en un numero finito de expresiones Sin embargo hay programas concurrentes que garantizan la interrupcion de ese termino en un numero infinito de estados Clinger 1981 Hewitt 2006 Reduccion optima EditarLevy define en su publicacion de 1988 Sharing in the Evaluation of lambda Expressions la nocion de compartir optimamente de forma que no se duplique el trabajo Por ejemplo realizar una reduccion beta en orden normal sobre l i x i i xx i II la reduce a II II El argumento II es duplicado por la aplicacion al primer termino lambda Si la reduccion se realizo en orden aplicativo primero se ahorra trabajo porque no se duplican esfuerzos lx xx II se reduce a lx xx I Por otra parte emplear orden aplicativo puede resultar en reducciones redundantes o incluso nunca reducirse a una forma normal Por ejemplo realizar una reduccion beta en orden normal en lf f I ly lx xx y I resulta en ly lx xx y I I lx xx II que puede ser realizado sin duplicar esfuerzos Hacer lo mismo pero en orden aplicativo resulta en lf f I ly y I y I ly y I y I I I I I I por lo que ahora el trabajo se duplica Levy muestra la existencia de terminos lambda donde no existe una secuencia de reducciones que las reduzca sin duplicar el trabajo a realizar El siguiente termino lambda es un ejemplo de estos terminos lg g g lx x lh lf f f lz z lw h w ly y Esta compuesto de tres terminos similares x lg lh y y lf lw z y z lw h w ly y Solo hay dos reducciones beta posibles sobre x y sobre y Reducir el termino x externo primero resulta en terminos duplicados el termino interno y el termino y y cada copia debe ser reducida pero reducir el termino y primero duplica su argumento z que causara que se duplique el trabajo cuando se conozcan los valores de h y w Curiosamente dicho termino se reduce a la funcion identidad ly y y se construye realizando encapsulaciones sucesivas La nocion precisa de trabajo duplicado se basa en darse cuenta de que tras hacerse la primera reduccion a I I el valor de otro I I puede determinarse porque tienen la misma estructura y tienen de hecho el mismo valor y resultan de un ancestro comun A dichas estructuras similares se les puede asignar una etiqueta que puede ser rastreada durante las reducciones Si un nombre es asignado a la redex que produce todos los terminos II resultantes despues todas las ocurrencias duplicadas de II pueden ser localizadas y reducidas de una vez Sin embargo no es obvio si una redex producira el termino II Identificar las estructuras que son similares en partes diferentes de un termino lambda puede requerir de algoritmos complejos y puede conllevar incluso una complejidad igual al historial de la reduccion misma Mientras Levy define la nocion de compartir optimamente no proporciona un algoritmo para hacerlo En la publicacion de Vincent van Oostrom Kees Jan van de Looij y Marijn Zwitserlood Lambdascope Another optimal implementation of the lambda calculus se proporciona tal algoritmo transformando terminos lambda en redes de interaccion que despues son reducidas En terminos generales la reduccion resultante es optima porque cada termino que tuviese la misma etiqueta segun el trabajo de Levy serian el mismo grafo en la red de interaccion En la publicacion mencionan que su prototipo de Lambdascope rinde de forma similar a la version optimizada de la implementacion de referencia de la BOHM Semantica EditarEl hecho de que los terminos del calculo lambda puedan actuar como funciones sobre otros terminos o incluso sobre si mismos llevo a cuestionarse la semantica del calculo lambda Se le puede asignar un significado a los terminos del calculo lambda La semantica natural era encontrar un conjunto D isomorfico al espacio de funciones D D de funciones de si mismo Sin embargo no puede existir tal D que no sea trivial por restricciones de cardinalidad porque el conjunto de todas las funciones de D a D tiene mayor cardinalidad que D a menos que sea un conjunto unitarioEn 1970 Dana Scott mostro que si solo se consideran funciones continuas un conjunto o dominio D con las propiedades necesarias se puede encontrar proporcionando por tanto un modelo para el calculo lambda Este trabajo tambien sento las bases para la semantica denotacional de los lenguajes de programacionReferencias Editar A Church A set of postulates for the foundation of logic Annals of Mathematics Series 2 33 346 366 1932 Kleene S C amp Rosser J B 1935 The inconsistency of certain formal logics Annals of Mathematics 36 3 630 636 doi 10 2307 1968646 Church A A Formulation of the Simple Theory of Types Journal of Symbolic Logic 5 1940 Abelson Harold amp Gerald Jay Sussman Structure and Interpretation of Computer Programs The MIT Press ISBN 0 262 51087 1 Barendregt Henk The lambda calculus its syntax and semantics North Holland 1984 is the comprehensive reference on the untyped lambda calculus see also the paper Introduction to Lambda Calculus Barendregt Henk The Type Free Lambda Calculus pp1091 1132 of Handbook of Mathematical Logic North Holland 1977 ISBN 0 7204 2285 X Church Alonzo An unsolvable problem of elementary number theory American Journal of Mathematics 58 1936 pp 345 363 This paper contains the proof that the equivalence of lambda expressions is in general not decidable Clinger William Foundations of Actor Semantics MIT Mathematics Doctoral Dissertation June 1981 Punit Gupta Amit amp Ashutosh Agte Untyped lambda calculus alpha beta and eta reductions and recursion Henz Martin The Lambda Calculus Formally correct development of the Lambda calculus Hewitt Carl What is Commitment Physical Organizational and Social COIN AAMAS April 27 2006 Kleene Stephen A theory of positive integers in formal logic American Journal of Mathematics 57 1935 pp 153 173 and 219 244 Contains the lambda calculus definitions of several familiar functions Landin Peter A Correspondence Between ALGOL 60 and Church s Lambda Notation Communications of the ACM vol 8 no 2 1965 pages 89 101 Available from the ACM site A classic paper highlighting the importance of lambda calculus as a basis for programming languages Larson Jim An Introduction to Lambda Calculus and Scheme A gentle introduction for programmers Some parts of this article are based on material from FOLDOC used with permission Miguel Angel Jimenez Santana Lambda Calculus Graphical InterpreterEnlaces externos EditarL Allison Algunos ejemplos ejecutables de calculo l en ingles Chris Barker Lambda tutorial Some executable Javascript Ejemplos simples con anotaciones en ingles Georg P Loczewski The Lambda Calculus and A Raul Rojas A Tutorial Introduction to the Lambda Calculus PDF David C Keenan To Dissect a Mockingbird A Graphical Notation for the Lambda Calculus with Animated Reduction Bret Victor Alligator Eggs A Puzzle Game Based on Lambda Calculus Miguel Angel Jimenez Santana Lambda Calculus Graphical Interpreter Camilo Chacon Sartori Introduccion al calculo lambda usando Racket espanol Datos Q242028 Multimedia Lambda calculusObtenido de https es wikipedia org w index php title Calculo lambda amp oldid 137622647, wikipedia, wiki, leyendo, leer, libro, biblioteca,

español

, española, descargar, gratis, descargar gratis, mp3, video, mp4, 3gp, jpg, jpeg, gif, png, imagen, música, canción, película, libro, juego, juegos