De Wikipedia, la enciclopedia libre
  (Redirigido de los números de la Iglesia )
Saltar a navegación Saltar a búsqueda

En matemáticas , la codificación de Church es un medio para representar datos y operadores en el cálculo lambda . Los números de la Iglesia son una representación de los números naturales utilizando notación lambda. El método lleva el nombre de Alonzo Church , quien primero codificó datos en el cálculo lambda de esta manera.

Los términos que generalmente se consideran primitivos en otras notaciones (como enteros, booleanos, pares, listas y uniones etiquetadas) se asignan a funciones de orden superior en la codificación de Church. La tesis de Church-Turing afirma que cualquier operador computable (y sus operandos) se puede representar bajo la codificación de Church. En el cálculo lambda sin tipo, el único tipo de datos primitivo es la función.

La codificación de Church no pretende ser una implementación práctica de tipos de datos primitivos. Su uso es para mostrar que no se requieren otros tipos de datos primitivos para representar ningún cálculo. La integridad es representativa. Se necesitan funciones adicionales para traducir la representación en tipos de datos comunes, para mostrarlos a las personas. En general, no es posible decidir si dos funciones son extensionalmente iguales debido a la indecidibilidad de equivalencia del teorema de Church . La traducción puede aplicar la función de alguna manera para recuperar el valor que representa, o buscar su valor como un término lambda literal.

El cálculo lambda se suele interpretar en el sentido de que utiliza la igualdad intensional . Existen problemas potenciales con la interpretación de los resultados debido a la diferencia entre la definición intensional y extensional de igualdad.

Números de la iglesia [ editar ]

Los números de la Iglesia son las representaciones de números naturales bajo la codificación de la Iglesia. La función de orden superior que representa el número natural n es una función que asigna cualquier función a su composición n- veces . En términos más simples, el "valor" del numeral es equivalente al número de veces que la función encapsula su argumento.

Todos los números de la Iglesia son funciones que toman dos parámetros. Los números de iglesia 0 , 1 , 2 , ..., se definen como sigue en el cálculo lambda .

Comenzando con 0 no aplicación de la función en absoluto, proceder con 1 aplicando la función una vez, 2 aplicando la función dos veces, 3 aplicando la función tres veces, etc. :

El número 3 de la Iglesia representa la acción de aplicar una función dada tres veces a un valor. La función proporcionada se aplica primero a un parámetro proporcionado y luego sucesivamente a su propio resultado. El resultado final no es el número 3 (a menos que el parámetro proporcionado sea 0 y la función sea una función sucesora ). La función en sí, y no su resultado final, es el número 3 de la Iglesia . El número 3 de la Iglesia significa simplemente hacer cualquier cosa tres veces. Es una demostración ostensiva de lo que se entiende por "tres tiempos".

Cálculo con números de la Iglesia [ editar ]

Las operaciones aritméticas sobre números pueden representarse mediante funciones sobre numerales de la Iglesia. Estas funciones pueden definirse en cálculo lambda o implementarse en la mayoría de los lenguajes de programación funcionales (consulte conversión de expresiones lambda en funciones ).

La función de suma usa la identidad .

La función sucesora es β-equivalente a .

La función de multiplicación usa la identidad .

La función exponencial es dada por la definición de los números de la Iglesia, . En la definición, sustitúyase por obtener y,

que da la expresión lambda,

La función es más difícil de entender.

Un numeral Church aplica una función n veces. La función predecesora debe devolver una función que aplique su parámetro n - 1 veces. Esto se logra construyendo un contenedor alrededor de f y x , que se inicializa de una manera que omite la aplicación de la función la primera vez. Consulte el predecesor para obtener una explicación más detallada.

La función de resta se puede escribir basándose en la función predecesora.

Tabla de funciones en los números de la Iglesia [ editar ]

* Tenga en cuenta que en la codificación de la Iglesia,

Derivación de la función predecesora [ editar ]

La función predecesora utilizada en la codificación de la Iglesia es,

.

Para construir el predecesor, necesitamos una forma de aplicar la función 1 vez menos. Un numeral n aplica la función f n veces ax . La función predecesora debe usar el numeral n para aplicar la función n -1 veces.

Antes de implementar la función predecesora, aquí hay un esquema que envuelve el valor en una función de contenedor. Definiremos nuevas funciones para usar en lugar de f y x , llamadas inc e init . La función de contenedor se llama valor . El lado izquierdo de la tabla muestra un número n aplicado a inc e init .

La regla general de recurrencia es,

Si también hay una función para recuperar el valor del contenedor (llamado extracto ),

Luego, extraer puede usarse para definir la función samenum como,

La función samenum no es intrínsecamente útil. Sin embargo, como inc delega la llamada de f a su argumento contenedor, podemos arreglar que en la primera aplicación inc reciba un contenedor especial que ignore su argumento permitiendo omitir la primera aplicación de f . Llame a este nuevo contenedor inicial const . El lado derecho de la tabla anterior muestra las expansiones de n inc const . Luego, al reemplazar init con const en la expresión de la misma función, obtenemos la función predecesora,

Como se explica a continuación, las funciones inc , init , const , value y extract pueden definirse como,

Lo que da la expresión lambda para pred como,

Otra forma de definir pred [ editar ]

Pred también se puede definir usando pares:

Esta es una definición más simple, pero conduce a una expresión más compleja para pred. La expansión para :

División [ editar ]

La división de números naturales se puede implementar mediante, [2]

El cálculo requiere muchas reducciones beta. A menos que haga la reducción a mano, esto no importa mucho, pero es preferible no tener que hacer este cálculo dos veces. El predicado más simple para probar números es IsZero, así que considere la condición.

Pero esta condición es equivalente a , no . Si se usa esta expresión, la definición matemática de división dada anteriormente se traduce en función en los números de la Iglesia como,

Como se desee, esta definición tiene una única llamada a . Sin embargo, el resultado es que esta fórmula da el valor de .

Este problema puede corregirse sumando 1 an antes de llamar a dividir . La definición de dividir es entonces,

dividir1 es una definición recursiva. El combinador Y se puede utilizar para implementar la recursividad. Cree una nueva función llamada div por;

  • En el lado izquierdo
  • En el lado derecho

Llegar,

Entonces,

dónde,

Da,

O como texto, usando \ para λ ,

dividir = (\ n. ((\ f. (\ xx x) (\ xf (xx))) (\ c. \ n. \ m. \ f. \ x. (\ d. (\ nn (\ x . (\ a. \ bb)) (\ a. \ ba)) d ((\ f. \ xx) fx) (f (cdmfx))) ((\ m. \ nn (\ n. \ f. \ xn (\ g. \ hh (gf)) (\ ux) (\ uu)) m) nm))) ((\ n. \ f. \ x. f (nfx)) n))

Por ejemplo, 9/3 está representado por

dividir (\ f. \ xf (f (f (f (f (f (f (f (f (fx))))))))) (\ f. \ xf (f (fx)))

Usando una calculadora de cálculo lambda, la expresión anterior se reduce a 3, usando el orden normal.

\ f. \ xf (f (f (x)))

Números firmados [ editar ]

Un método simple para extender los números de la iglesia a números con signo es usar un par de iglesias que contenga números de la iglesia que representen un valor positivo y uno negativo. [3] El valor entero es la diferencia entre los dos números de la Iglesia.

Un número natural se convierte en un número con signo mediante,

La negación se realiza intercambiando los valores.

El valor entero se representa de forma más natural si uno de los pares es cero. La función OneZero logra esta condición,

La recursividad se puede implementar usando el combinador Y,

Más y menos [ editar ]

La suma se define matemáticamente en el par por,

La última expresión se traduce al cálculo lambda como,

De manera similar se define la resta,

donación,

Multiplica y divide [ editar ]

La multiplicación se puede definir por,

La última expresión se traduce al cálculo lambda como,

Aquí se da una definición similar para la división, excepto en esta definición, un valor en cada par debe ser cero (ver OneZero arriba). La función divZ nos permite ignorar el valor que tiene un componente cero.

divZ se usa en la siguiente fórmula, que es la misma que para la multiplicación, pero con mult reemplazado por divZ .

Números racionales y reales [ editar ]

Los números reales racionales y computables también se pueden codificar en el cálculo lambda. Los números racionales se pueden codificar como un par de números con signo. Los números reales computables pueden codificarse mediante un proceso de limitación que garantiza que la diferencia del valor real difiera en un número que puede ser tan pequeño como necesitemos. [4] [5] Las referencias dadas describen software que, en teoría, podría traducirse al cálculo lambda. Una vez que se definen los números reales, los números complejos se codifican naturalmente como un par de números reales.

Los tipos de datos y las funciones descritas anteriormente demuestran que cualquier tipo de datos o cálculo puede codificarse en el cálculo lambda. Ésta es la tesis de Church-Turing .

Traducción con otras representaciones [ editar ]

La mayoría de los lenguajes del mundo real admiten números enteros nativos de la máquina; las funciones de iglesia y no iglesia convierten entre números enteros no negativos y sus correspondientes números de iglesia. Las funciones se dan aquí en Haskell , donde \corresponde al λ del cálculo Lambda. Las implementaciones en otros idiomas son similares.

tipo  Iglesia  a  =  ( a  ->  a )  ->  a  ->  aiglesia  ::  Entero  ->  Iglesia  Entero iglesia  0  =  \ f  ->  \ x  ->  x iglesia  n  =  \ f  ->  \ x  ->  f  ( iglesia  ( n - 1 )  f  x )unchurch  ::  Church  Integer  ->  Integer unchurch  cn  =  cn  ( +  1 )  0

Iglesia booleana [ editar ]

Church Booleanos son la codificación de Church de los valores booleanos verdadero y falso. Algunos lenguajes de programación los utilizan como modelo de implementación para la aritmética booleana; ejemplos son Smalltalk y Pico .

La lógica booleana puede considerarse una opción. La codificación de la Iglesia de verdadero y falso son funciones de dos parámetros:

  • true elige el primer parámetro.
  • false elige el segundo parámetro.

Las dos definiciones se conocen como Church Booleanos:

Esta definición permite que los predicados (es decir, funciones que devuelven valores lógicos ) actúen directamente como cláusulas if. Una función que devuelve un booleano, que luego se aplica a dos parámetros, devuelve el primero o el segundo parámetro:

se evalúa como cláusula-entonces si el predicado x se evalúa como verdadero , y como cláusula-else si el predicado x se evalúa como falso .

Dado que verdadero y falso eligen el primer o segundo parámetro, se pueden combinar para proporcionar operadores lógicos. Tenga en cuenta que hay dos versiones de no , dependiendo de la estrategia de evaluación que se elija.

Algunos ejemplos:

Predicados [ editar ]

Un predicado es una función que devuelve un valor booleano. El predicado más fundamental es , que devuelve si su argumento es el número de la Iglesia , y si su argumento es cualquier otro número de la Iglesia:

El siguiente predicado prueba si el primer argumento es menor o igual que el segundo:

,

Por la identidad,

La prueba de igualdad se puede implementar como,

Pares de iglesias [ editar ]

Los pares de iglesias son la codificación de la iglesia del tipo de pares (dos tuplas). El par se representa como una función que toma un argumento de función. Cuando se le dé su argumento, lo aplicará a los dos componentes del par. La definición en el cálculo lambda es,

Por ejemplo,

Enumerar codificaciones [ editar ]

Una lista ( inmutable ) se construye a partir de nodos de lista. Las operaciones básicas de la lista son;

A continuación, ofrecemos cuatro representaciones diferentes de listas:

  • Construya cada nodo de lista a partir de dos pares (para permitir listas vacías).
  • Construya cada nodo de lista a partir de un par.
  • Represente la lista usando la función de plegado derecho .
  • Representar la lista usando la codificación de Scott que toma casos de expresión de coincidencia como argumentos

Dos pares como un nodo de lista [ editar ]

Una lista no vacía puede ser implementada por un par de iglesias;

  • Primero contiene la cabeza.
  • El segundo contiene la cola.

Sin embargo, esto no da una representación de la lista vacía, porque no hay un puntero "nulo". Para representar nulo, el par se puede envolver en otro par, dando valores libres,

  • Primero : es el puntero nulo (lista vacía).
  • Segundo, primero contiene la cabeza.
  • Segundo, el segundo contiene la cola.

Usando esta idea, las operaciones básicas de la lista se pueden definir así: [6]

En un nodo nulo, nunca se accede al segundo , siempre que el encabezado y el final solo se apliquen a listas no vacías.

Un par como nodo de lista [ editar ]

Alternativamente, defina [7]

donde la última definición es un caso especial de la general

Represente la lista usando el pliegue derecho [ editar ]

Como alternativa a la codificación mediante pares de iglesias, se puede codificar una lista identificándola con su función de plegado derecho . Por ejemplo, una lista de tres elementos x, y y z se puede codificar mediante una función de orden superior que cuando se aplica a un combinador cy un valor n devuelve cx (cy (czn)).

Esta representación de la lista se puede dar el tipo de sistema F .

Representar la lista con la codificación Scott [ editar ]

Una representación alternativa es la codificación de Scott, que utiliza la idea de continuaciones y puede conducir a un código más simple. [8] (ver también codificación Mogensen-Scott ).

En este enfoque, utilizamos el hecho de que las listas se pueden observar mediante la expresión de coincidencia de patrones. Por ejemplo, usando la notación Scala , si listdenota un valor de tipo Listcon una lista Nily un constructor vacíos Cons(h, t), podemos inspeccionar la lista y calcular nilCodeen caso de que la lista esté vacía y consCode(h, t)cuando la lista no esté vacía:

lista de  coincidencias  {  case  Nil  =>  nilCode  case  Cons ( h ,  t )  =>  consCode ( h , t ) }

La 'lista' viene dada por cómo actúa sobre 'nilCode' y 'consCode'. Por lo tanto, definimos una lista como una función que acepta tales 'nilCode' y 'consCode' como argumentos, de modo que en lugar de la coincidencia de patrón anterior simplemente podemos escribir:

Denotemos por 'n' el parámetro correspondiente a 'nilCode' y por 'c' el parámetro correspondiente a 'consCode'. La lista vacía es la que devuelve el argumento nulo:

La lista no vacía con la cabeza 'h' y la cola 't' viene dada por

De manera más general, un tipo de datos algebraicos con alternativas se convierte en una función con parámetros. Cuando el constructor tiene argumentos, el parámetro correspondiente de la codificación también toma argumentos.

La codificación de Scott se puede realizar en cálculo lambda sin tipo, mientras que su uso con tipos requiere un sistema de tipos con recursividad y polimorfismo de tipos. Una lista con el tipo de elemento E en esta representación que se utiliza para calcular valores de tipo C tendría la siguiente definición de tipo recursivo, donde '=>' denota el tipo de función:

tipo  Lista  =  C  =>  // argumento nulo  ( E  =>  Lista  =>  C )  =>  // argumento contras  C  // resultado de la coincidencia de patrones

Una lista que se puede utilizar para calcular tipos arbitrarios tendría un tipo que cuantifica C. Una lista genérica [ aclaración necesaria ] en el Etambién tomaría Ecomo el argumento de tipo.

Ver también [ editar ]

  • Cálculo lambda
  • Sistema F para los números de la Iglesia en un cálculo mecanografiado
  • Codificación Mogensen-Scott
  • Definición de Von Neumann de ordinales : otra forma de codificar números naturales: como conjuntos

Notas [ editar ]

  1. ^ Esta fórmula es la definición de un número de Iglesia n con f -> m, x -> f.
  2. ^ Allison, Lloyd. "Enteros de cálculo Lambda" .
  3. ^ Bauer, Andrej. "Respuesta de Andrej a una pregunta;" Representación de números negativos y complejos mediante cálculo lambda " " .
  4. ^ "Aritmética real exacta" . Haskell .
  5. ^ Bauer, Andrej. "Software computacional de números reales" .
  6. ^ Pierce, Benjamin C. (2002). Tipos y lenguajes de programación . Prensa del MIT . pag. 500. ISBN 978-0-262-16209-8.
  7. ^ Tromp, John (2007). "14. Cálculo lambda binario y lógica combinatoria". En Calude, Cristian S (ed.). Aleatoriedad y complejidad, de Leibniz a Chaitin . World Scientific. págs. 237-262. ISBN 978-981-4474-39-9.
    Como PDF: Tromp, John (14 de mayo de 2014). "Cálculo lambda binario y lógica combinatoria" (PDF) . Consultado el 24 de noviembre de 2017 .
  8. ^ Jansen, Jan Martin (2013). "Programación en el λ-cálculo: de la iglesia a Scott y viceversa". LNCS . 8106 : 168–180. doi : 10.1007 / 978-3-642-40355-2_12 .

Referencias [ editar ]

  • Metaprogramación directamente reflexiva
  • Números de iglesia y booleanos explicados por Robert Cartwright en Rice University
  • Fundamentos teóricos para la práctica 'Programación totalmente funcional' (Capítulos 2 y 5) Todo sobre Church y otras codificaciones similares, incluyendo cómo derivarlas y operaciones en ellas, desde los primeros principios
  • Algunos ejemplos interactivos de numerales de la Iglesia
  • Tutorial de Lambda Calculus Live: Álgebra booleana