Je voudrais savoir si un type universellement quantifié : est un sous-type, ou cas particulier, de type existentiellement quantifié avec la même signature:
Je dirais "oui": si quelque chose est vrai "pour tous les X" ( pour tous les X ), alors cela doit aussi être vrai "pour certains X" ( ). Autrement dit, une instruction avec « » est simplement une version plus restreinte de la même instruction avec « »:
Ai-je tort quelque part?
Contexte: pourquoi est-ce que je demande cela?
J'étudie les types existentiels afin de comprendre pourquoi et comment les "types [de données] abstraits ont un type existentiel" . Je ne peux pas avoir une bonne compréhension de ce concept par la seule théorie; J'ai aussi besoin d'exemples concrets.
Malheureusement, il est difficile de trouver de bons exemples de code car la plupart des langages de programmation ne prennent en charge que peu de types existentiels. (Par exemple, les caractères génériques de Haskell
forall
ou Java?
.) D'un autre côté, les types universellement quantifiés sont pris en charge par de nombreux langages récents via des "génériques".Pire encore, les génériques semblent facilement se mélanger avec les types existentiels , ce qui rend encore plus difficile de distinguer les types existentiels des types universels. Je suis curieux de savoir pourquoi cette confusion se produit si facilement. Une réponse à cette question pourrait l'expliquer: si les types universels ne sont en effet qu'un cas particulier de types existentiels, il n'est pas étonnant que les types génériques, par exemple Java
List<T>
, puissent être interprétés dans un sens ou dans l'autre.
la source
forall x. P(x)
alorsexists x. P(x)
. Si les systèmes de types en tiennent compte lors de la vérification des types ... Je n'en ai aucune idée. +1 pour une question intéressante.Réponses:
D'abord, d'un point de vue mathématique, n'implique pas ∃ x : T , P ( x ) . L'implication est valable si et seulement si T n'est pas vide. Cependant, dans les langages de programmation, il est rare de traiter des types vides (bien que cela se produise).∀x:T,P(x) ∃x:T,P(x) T
Toujours d'un point de vue mathématique, même lorsque , les deux ne sont pas les mêmes. Si vous donnez aux types une sémantique définie, alors T a est un sur-ensemble de T e , pas le même type. (En fait, ce n'est pas un sur-ensemble; il est presque isomorphe à un sur-ensemble.)(∀x:T,P(x))⇒(∃x:T,P(x)) Ta Te
Rapprochez-vous de la théorie du langage de programmation et voyons ce que ces types signifient réellement. est un type universel: si vous avez une valeur A de ce type, vous pouvez construire A ( M ) pour tout M : X . En particulier, si vous avez M 1 et M 2 de type X , vous pouvez construire A ( MTa=∀X.{a:X,f:X→bool} A A(M) M:X M1 M2 X et A ( M 2 ) . En substance (et éventuellement en vigueur, selon la langue) T a est une fonction des types aux termes. En tant que tel, le type universel fournit uneparamétrisation detype: une valeur valable pour tous les types. Les types universels sont au cœur dupolymorphisme.A(M1) A(M2) Ta
Le type existentielle est une bête bien différente. Étant donné une valeur B de type T e , il n'y a qu'un seul terme N : X tel que π 1 ( B ) = N , et pour ce terme π 2 ( B ) = { a : N , f :Te=∃X.{a:X,f:X→bool} B Te N:X π1(B)=N . Le type existentiel fournit un moyen de masquer la nature de N ; il dit: «Il existe un type! Mais je ne vous dirai pas quoi! ». En tant que tel, le type existentiel fournit uneabstraction detype: une valeur cachée spécifique. Les types existentiels sont au cœur dessystèmesdemodules.π2(B)={a:N,f:N→bool} N
Ne vous laissez pas induire en erreur par Haskell
forall
: malgré son nom, c'est une forme de quantificateur existentiel.Pour le fond, je recommande fortement les types et les langages de programmation (les chapitres 23 et 24 traitent respectivement des types universels et des types existentiels). Il fournira un contexte utile pour comprendre les articles de recherche.
la source
forall
est en effet un quantificateur universel dans le contexte original de la quantification implicite qu'il rend explicite, à savoir la visualisation des types polymorphes "de l'extérieur" pour les définitions de haut niveau. A "l'intérieur" d'une telle définition, lors de la manipulation d'arguments, les types polymorphes sont effectivement existentiels; chaque variable de type est liée à un certain type, mais nous ne savons pas (et ne pouvons pas) savoir ce qu'est ce type. À ma connaissance, aucune implémentation Haskell ne prend en charge les vrais types existentiels (bruts, de niveau supérieur), et je ne sais pas à quoi cela pourrait même servir.Votre intuition que doit être intégrables dans ∃ X .∀X.P(X) ∃X.P(X)
L'article que vous mentionnez pour les types existentiels est un peu théorique. Un article plus didacticiel est l'article de Cardelli et Wegner: sur la compréhension des types, l'abstraction des données et le polymorphisme . La plupart des manuels avancés sur les langages de programmation auraient également une discussion sur les types existentiels. Un bon livre à rechercher serait les fondations de Mitchell des langages de programmation .
Vous avez raison de dire que la plupart des langages de programmation n'ont pas explicitement de types existentiels. Cependant, beaucoup ont des types abstraits (ou sous un autre nom tel que "packages" ou "modules"). Ainsi, ils sont capables d' exprimer des valeurs de types existentiels, même s'ils ne traitent pas ces valeurs comme des entités de première classe.
la source