Soy nuevo en la teoría del lenguaje de programación. Estaba viendo algunas conferencias en línea en las que el instructor afirmó que una función con tipo polimórfico forall t: Type, t->t
sería la identidad, pero no explicó por qué. ¿Alguien puede explicarme por qué? Tal vez una prueba de la afirmación de los primeros principios.
programming-languages
type-theory
abhishek
fuente
fuente
Respuestas:
Lo primero a tener en cuenta es que esto no es necesariamente cierto. Por ejemplo, dependiendo del idioma, una función con ese tipo, además de ser la función de identidad, podría: 1) hacer un bucle para siempre, 2) mutar algún estado, 3) devolver
null
, 4) lanzar una excepción, 5) realizar alguna E / S, 6) bifurcar un hilo para hacer otra cosa, 7) hacercall/cc
travesuras, 8) usar algo como el de JavaObject.hashCode
, 9) usar la reflexión para determinar si el tipo es un número entero e incrementarlo si es así, 10) usar la reflexión para analizar la pila de llamadas y hacer algo basado en el contexto dentro del cual se llama, 11) probablemente muchas otras cosas y ciertamente combinaciones arbitrarias de lo anterior.Entonces, la propiedad que conduce a esto, la parametricidad, es una propiedad del lenguaje en su conjunto y hay variaciones más fuertes y más débiles. Para muchos de los cálculos formales estudiados en la teoría de tipos, ninguno de los comportamientos anteriores puede ocurrir. Por ejemplo, para el Sistema F / el cálculo lambda polimórfico puro, donde se estudió por primera vez la parametricidad, ninguno de los comportamientos anteriores puede ocurrir. Simplemente no tiene excepciones, el estado mutable,
null
,call/cc
, E / S, la reflexión, y está fuertemente normalizando por lo que no puede reproducirse en bucle para siempre. Como Gilles mencionó en un comentario, ¡ Theorems de papel gratis!por Phil Wadler es una buena introducción a este tema y sus referencias irán más allá en la teoría, específicamente en la técnica de las relaciones lógicas. Ese enlace también enumera algunos otros documentos de Wadler sobre el tema de la parametricidad.Dado que la parametricidad es una propiedad del lenguaje, para probarlo se requiere primero articular formalmente el lenguaje y luego un argumento relativamente complicado. El argumento informal para este caso particular, suponiendo que estamos en el cálculo lambda polimórfico es que, dado que no sabemos nada,
t
no podemos realizar ninguna operación en la entrada (por ejemplo, no podemos incrementarla porque no sabemos si es un número) o cree un valor de ese tipo (por lo que sabemost
=Void
, un tipo sin ningún valor). La única forma de producir un valor de tipot
es devolver el que se nos da. No hay otros comportamientos posibles. Una forma de ver eso es usar una fuerte normalización y demostrar que solo hay un término de forma normal de este tipo.fuente
La prueba del reclamo es bastante compleja, pero si eso es lo que realmente desea, puede consultar el documento original de Reynolds sobre el tema.
La idea clave es que se cumple para las funciones polimórficas paramétricas , donde el cuerpo de una función polimórfica es el mismo para todas las instancias monomórficas de la función. En dicho sistema, no se pueden hacer suposiciones sobre el tipo de un parámetro de tipo polimórfico, y si el único valor en el alcance tiene un tipo genérico, no hay nada que ver con él, sino devolverlo o pasarlo a otras funciones que usted ' he definido, que a su vez no puede hacer nada más que devolverlo o pasarlo .. .etc. Entonces, al final, todo lo que puede hacer es una cadena de funciones de identidad antes de devolver el parámetro.
fuente
Con todas las advertencias que menciona Derek, e ignorando las paradojas que resultan del uso de la teoría de conjuntos, permítanme esbozar una prueba en el espíritu de Reynolds / Wadler.
Una función del tipo:
es una familia de funciones indexadas por tipo t .Ft t
La idea es que, para definir formalmente funciones polimórficas, no deberíamos tratar los tipos como conjuntos de valores, sino más bien como relaciones. Tipos básicos, como
Int
inducir relaciones de igualdad, por ejemplo, dosInt
valores están relacionados si son iguales. Las funciones están relacionadas si asignan valores relacionados a valores relacionados. El caso interesante son las funciones polimórficas. Asignan tipos relacionados a valores relacionados.En nuestro caso, queremos establecer una relación entre dos funciones polimórficas y g del tipo:F sol
Suponga que el tipo está relacionado con el tipo t . La primera función f asigna el tipo s a un valor: aquí, el valor en sí es una función f s del tipo s → s . La segunda función asigna el tipo t a otro valor g t del tipo t → t . Decimos que f está relacionado con g si los valores f ss t F s Fs s → s t solt t → t F sol Fs solt
f
s
t
()
()
t
()
t
((), c)
c
t
()
()
c
c
()
c
t
f
id
Puedes encontrar más detalles en mi blog .
fuente
EDITAR: Un comentario anterior ha proporcionado la pieza que falta. Algunas personas están jugando deliberadamente con idiomas menos completos. Explícitamente no me importan esos lenguajes. Un lenguaje realmente útil que no sea completo es una locura difícil de diseñar. Todo lo demás se expande sobre lo que sucede tratando de aplicar estos teoremas a un lenguaje completo.
¡Falso!
donde el
is
operador compara dos variables para la identidad de referencia. Es decir, contienen el mismo valor. No es un valor equivalente, el mismo valor. Funcionesf
yg
son equivalentes por alguna definición, pero no son lo mismo.Si esta función se pasa a sí misma, devuelve algo más; de lo contrario, devuelve su entrada. El algo más tiene el mismo tipo que sí mismo, por lo tanto, puede ser sustituido. En otras palabras,
f
no es la identidad, porquef(f)
regresag
, mientras que la identidad volveríaf
.Para que el teorema se mantenga tiene que asumir la capacidad ridícula de reducir
Si está dispuesto a asumir que puede asumir que se puede manejar la inferencia de tipos mucho más fácil.
Si tratamos de restringir el dominio hasta que se mantenga el teorema, terminamos teniendo que restringirlo terriblemente lejos.
raise
y noexit
. Ahora estamos empezando a estar limitados.nil
. Esto está empezando a ser problemático. Nos hemos quedado sin formas de lidiar con 1 / 0.³La existencia de las dos últimas restricciones ha paralizado el lenguaje. Si bien aún está completando Turing, la única forma de obtener un trabajo de propósito general es simular una plataforma interna que interprete un lenguaje con requisitos más flexibles.
¹ Si crees que el compilador puede deducir ese, prueba este
² La prueba de que el compilador no puede hacer esto depende del cegamiento. Podemos usar varias bibliotecas para asegurarnos de que el compilador no pueda ver el ciclo a la vez. Además, siempre podemos construir algo donde el programa funcionaría pero no podría compilarse porque el compilador no puede realizar la inducción en la memoria disponible.
³ Alguien piensa que puede devolver este valor nulo sin que los tipos genéricos arbitrarios devuelvan nulo. Esto paga una penalidad desagradable por la cual no he visto un lenguaje efectivo que pueda pagarlo.
No debe compilar. El problema fundamental es que la indexación de la matriz en tiempo de ejecución ya no funciona.
fuente
foil
cuantificador de todos modos?) Esto no es útil en absoluto.