EDIT: Un commentaire ci-dessus a fourni la pièce manquante. Certaines personnes jouent délibérément avec des langues qui ne sont pas complètes. Je ne me soucie pas explicitement de ces langues. Un langage vraiment non utilisable et complètement utilisable est une chose difficile à concevoir. Le reste de tout cela se développe sur ce qui se passe en essayant d'appliquer ces théorèmes à un langage complet.
Faux!
function f(a): forall t: Type, t->t
function g(a): forall t: Type, t->t
return (a is g) ? f : a
return a is f ? g : a
où l' is
opérateur compare deux variables pour l'identité de référence. Autrement dit, ils contiennent la même valeur. Pas une valeur équivalente, même valeur. Les fonctions f
et g
sont équivalentes par définition mais elles ne sont pas les mêmes.
Si cette fonction est passée elle-même, elle renvoie autre chose; sinon, il renvoie son entrée. Le quelque chose d'autre a le même type que lui, il peut donc être remplacé. En d'autres termes, ce f
n'est pas l'identité, car f(f)
revient g
, alors que l'identité reviendrait f
.
Pour que le théorème tienne, il doit assumer la capacité ridicule de réduire
function cantor(n, <z, a>) : forall t: t: Type int, <int, t> -> <int, t>
return n > 1 ? cantor((n % 2 > 0) ? (n + 1) : n / 2, <z + 1, a>) : <z, a>
return cantor(1000, <0, a>)[1]¹
Si vous êtes prêt à supposer que vous pouvez supposer que l'inférence de type beaucoup plus facile peut être gérée.
Si nous essayons de restreindre le domaine jusqu'à ce que le théorème se vérifie, nous finissons par devoir le restreindre terriblement.
- Fonctionnel pur (pas d'état mutable, pas d'E / S). OK je peux vivre avec ça. Beaucoup de temps, nous voulons exécuter des preuves sur les fonctions.
- Bibliothèque standard vide. meh.
- Non
raise
et non exit
. Maintenant, nous commençons à être contraints.
- Il n'y a pas de type inférieur.
- Le langage a une règle qui permet au compilateur de réduire la récursion infinie en supposant qu'il doit se terminer. Le compilateur est autorisé à rejeter la récursion infinie triviale.
- Le compilateur est autorisé à échouer s'il est présenté avec quelque chose qui ne peut pas être prouvé dans les deux cas.² Maintenant, la bibliothèque standard ne peut pas prendre les fonctions comme arguments. Huer.
- Il n'y en a pas
nil
. Cela commence à devenir problématique. Nous avons manqué de moyens pour faire face à 1 / 0.³
- Le langage ne peut pas faire d'inférence de type de branche et n'a pas de priorité pour quand le programmeur peut prouver une inférence de type que le langage ne peut pas. C'est assez mauvais.
L'existence des deux dernières contraintes a paralysé la langue. Bien qu'il soit encore complet sur Turing, le seul moyen d'en tirer un travail général est de simuler une plate-forme interne qui interprète un langage avec des exigences plus lâches.
¹ Si vous pensez que le compilateur peut en déduire celui-ci, essayez celui-ci
function fermat(z) : int -> int
function pow(x, p)
return p = 0 ? 1 : x * pow(x, p - 1)
function f2(x, y, z) : int, int, int -> <int, int>
left = pow(x, 5) + pow(y, 5)
right = pow(z, 5)
return left = right
? <x, y>
: pow(x, 5) < right
? f2(x + 1, y, z)
: pow(y, 5) < right
? f2(2, y + 1, z)
: f2(2, 2, z + 1)
return f2(2, 2, z)
function cantor(n, <z, a>) : forall t: t: Type int, <int, t> -> <int, t>
return n > 1 ? cantor((n % 2 > 0) ? (n + 1) : n / 2, <z + 1, a>) : <z, a>
return cantor(fermat(3)[0], <0, a>)[1]
² La preuve que le compilateur ne peut pas faire cela dépend de l'aveuglement. Nous pouvons utiliser plusieurs bibliothèques pour nous assurer que le compilateur ne peut pas voir la boucle à la fois. De plus, nous pouvons toujours construire quelque chose où le programme fonctionnerait mais ne pourrait pas être compilé car le compilateur ne peut pas effectuer l'induction dans la mémoire disponible.
³ Quelqu'un pense que vous pouvez avoir ce retour nul sans que les types génériques arbitraires retournent nul. Cela paie une pénalité désagréable pour laquelle je n'ai vu aucun langage efficace qui puisse le payer.
function f(a, b, c): t: Type: t[],int,int->t
return a[b/c]
ne doit pas compiler. Le problème fondamental est que l'indexation des tableaux d'exécution ne fonctionne plus.