Supposons que nous sommes à l'entrée n :: Int
lors de l'exécution formulaire de STDIN. Nous avons ensuite lu n
des chaînes, et de les stocker en vn :: Vect n String
(semblant pour l'instant, ce qui peut être fait).
De même, on peut lire, m :: Int
et vm :: Vect m String
. Enfin, nous concaténer les deux vecteurs: vn ++ vm
(en simplifiant un peu ici). Cela peut être vérifié, et de type Vect (n+m) String
.
Maintenant il est vrai que le vérificateur de types s'exécute au moment de la compilation, avant que les valeurs n,m
sont connus, et aussi avant d' vn,vm
sont connus. Mais ce n'est pas grave: on peut toujours raison symboliquement sur les inconnues n,m
, et dire que d' vn ++ vm
a ce type, impliquant n+m
, même si nous ne savons pas encore quel n+m
est en réalité.
Il n'est pas si différent que ça de faire des mathématiques, où l'on manipule des expressions symboliques impliquant des variables inconnues, selon certaines règles, même si nous ne connaissons pas les valeurs des variables. Nous n'avons pas besoin de savoir quel est le nombre n
de voir qu' n+n = 2*n
.
De même, le type checker permet de vérification de type
-- pseudocode
readNStrings :: (n :: Int) -> IO (Vect n String)
readNStrings O = return Vect.empty
readNStrings (S p) = do
s <- getLine
vp <- readNStrings p
return (Vect.cons s vp)
(Eh bien, en fait, certains de plus d'aide de la programmeur pourrait être nécessaire pour typecheck, puisque cela implique dépendante de la correspondance et de la récursivité. Mais je vais négligence à ce sujet).
Surtout, le type de vérificateur peut vérifier que, sans le savoir ce qu' n
est.
Notez que la même question déjà soulevée par des fonctions polymorphes.
fst :: forall a b. (a, b) -> a
fst (x, y) = x
test1 = fst @ Int @ Float (2, 3.5)
test2 = fst @ String @ Bool ("hi!", True)
...
On peut se demander "comment l'typechecker vérifiez fst
sans savoir à quels types a
et b
sera au moment de l'exécution?". Encore une fois, par un raisonnement symbolique.
Avec des arguments de type c'est sans doute plus évident puisque nous avons l'habitude d'exécuter les programmes après l'effacement, à la différence de la valeur des paramètres tels que notre - n :: Int
- dessus, qui ne peuvent pas être effacées. Encore, il ya une certaine similitude entre universellement quantifier plus de types ou plus Int
.