¿Son los tipos universales un subtipo, o caso especial, de tipos existenciales?


20

Me gustaría saber si un tipo universalmente cuantificado : T a = X : { a X , f : X { T , F } } es un subtipo o caso especial, de un caso cuantificado existencialmente escriba T e con la misma firma: T e = X : { a X , f : X { T , F } }Ta

Ta=X:{aX,f:X{T,F}}
Te
Te=X:{aX,f:X{T,F}}

Yo diría "sí": si algo es cierto "para todas las X" ( ), entonces también debe ser cierto "para algunas X" ( X ). Es decir, una declaración con ' ' es simplemente una versión más restringida de la misma declaración con ' ': X , P ( X ) ?XX

X,P(X)?X,P(X).

¿Me equivoco en alguna parte?

Antecedentes: ¿por qué pregunto esto?

Estoy estudiando tipos existenciales para entender por qué y cómo los "tipos abstractos [de datos] tienen tipo existencial" . No puedo entender bien este concepto solo de la teoría; También necesito ejemplos concretos.

Desafortunadamente, es difícil encontrar buenos ejemplos de código porque la mayoría de los lenguajes de programación solo tienen soporte limitado para tipos existenciales. (Por ejemplo, los comodines de Haskellforall o Java? ). Por otro lado, los tipos cuantificados universalmente son compatibles con muchos idiomas recientes a través de "genéricos".

Lo que es peor, los genéricos también se mezclan fácilmente con los tipos existenciales , lo que hace que sea aún más difícil distinguir los tipos existenciales de los universales. Tengo curiosidad por qué esta confusión ocurre tan fácilmente. Una respuesta a esta pregunta podría explicarlo: si los tipos universales son solo un caso especial de tipos existenciales, entonces no es de extrañar que los tipos genéricos, por ejemplo, Java List<T>, puedan interpretarse de cualquier manera.


1
¿Cuál es la diferencia entre universal y existencial?

Matemáticamente hablando, tienes razón: si es forall x. P(x)así exists x. P(x). Si los sistemas de tipos tienen esto en cuenta al verificar los tipos ... No tengo idea. +1 para una pregunta interesante.

1
@deinan: si P (x) no se cumple para ninguna x , entonces ciertamente ∀xP (x) no se cumple. Lo que probablemente quisiste decir es que cuando no hay x , es decir, ∀x∈XP (x) no implica ∃x∈XP (x) si X = ∅ .

1
... Y tenga en cuenta que si se reescriben sin la notación establecida, se verán diferentes: ∀xx∈X⇒P (x) vs. ∃xx∈X & P (x) y que ∃xx∈X⇒P (x) será trivialmente satisfecha por cualquier x no de X .

1
Buena pregunta En Haskell es cierto que un valor de tipo (forall b. Show b => b) puede pasarse a una función que toma a (forall b. B), pero no al revés, lo que implica la sustituibilidad que esperaría de Una relación de subtipo. Pero, por supuesto, cuando habla de tipos, debe mencionar el sistema de tipos que está viendo, especialmente si tiene un álgebra de tipos formal en mente para su semántica ...

Respuestas:


10

x:T,P(x)x:T,P(x)T

(x:T,P(x))(x:T,P(x))TaTe

Ta=X.{a:X,f:Xbool}AA(M)M:XM1M2XA(M1)A(M2)Ta

Te=X.{a:X,f:Xbool}BTeN:Xπ1(B)=Nπ2(B)={a:N,f:Nbool}N

No se deje engañar por Haskell's forall: a pesar de su nombre, es una forma de cuantificador existencial.

Para antecedentes, recomiendo los Tipos y Lenguajes de Programación (los capítulos 23 y 24 discuten los tipos universales y los tipos existenciales respectivamente). Proporcionará información útil para comprender los artículos de investigación.


1
Una objeción menor, y bastante tardía: la de Haskell foralles de hecho un cuantificador universal en el contexto original de la cuantificación implícita que hace explícita, es decir, ver los tipos polimórficos "desde afuera" para definiciones de nivel superior. En el "interior" de tal definición, al manipular argumentos, los tipos polimórficos son efectivamente existenciales; cada variable de tipo está vinculada a algún tipo, pero no sabemos (y no podemos) cuál es ese tipo. Que yo sepa, ninguna implementación de Haskell admite tipos existenciales verdaderos (sin procesar, de nivel superior), y no me queda claro para qué propósito serviría.
CA McCann

1
Los tipos existenciales soportados por GHC son tipos que (directa o indirectamente) tienen cuantificadores universales que, vistos desde "afuera", ocurren en posición contravariante. Esto utiliza aproximadamente la misma dualidad que la negación lógica, por lo que para tener estos tipos existenciales en el nivel superior deben ser doblemente contravariantes, utilizando una codificación similar a CPS (esta es la equivalencia que Uday Reddy da). Tenga en cuenta que los cuantificadores existenciales en intuicionista presentan inconvenientes similares por razones similares.
CA McCann

5

X.P(X)X.P(X)

X.(X×(XBool))XX.(X×(XBool))

 f (p: \forall X. (X * (X -> Bool))) = PACK X = Bool WITH p[Bool]

El artículo que mencionas para los tipos existenciales es un poco teórico. Un artículo más tutorial es el artículo de Cardelli y Wegner: sobre comprensión de tipos, abstracción de datos y polimorfismo . Los libros de texto más avanzados sobre lenguajes de programación también tendrían alguna discusión sobre los tipos existenciales. Un buen libro para buscar sería los Fundamentos de los lenguajes de programación de Mitchell .

Tiene razón en que la mayoría de los lenguajes de programación no tienen tipos existenciales explícitamente. Sin embargo, muchos tienen tipos abstractos (o por algún otro nombre, como "paquetes" o "módulos"). Por lo tanto, pueden expresar valores de tipos existenciales, a pesar de que no tratan dichos valores como entidades de primera clase.

X.P(X)Y.(X.P(X)Y)Y

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.