• Aucun résultat trouvé

La figure 2 donne notre syst`eme de r`egles de typage pour le langage. La relation de typage comporte un contexte de typage Γ et un ensemble S de contraintes de type. La relation Γ, S ⊢ e : τ se lit « dans le contexte Γ, l’expression e a le type s(τ ) pour toute solution s de S ». La pr´esence d’un ensemble de contraintes dans la relation de typage est standard dans les syst`emes d’inf´erence de types en pr´esence de sous-typage [FM88]. Toutes les r`egles sauf les r`egles (trans) et (trans all) sont assez classiques. D´ecrivons bri`evement les r`egles standard puis d´etaillons les r`egles (trans) et (trans all).

(var) : Cette r`egle correspond `a la r`egle standard de Hindley/Milner.

(const) : T C donne les sch´emas de types des constantes.

(fun) et (app) : La r`egle (fun) correspond `a celle de Hindley/Milner. Dans (app) la contrainte impose que le type de l’argument pass´e `a la fonction soit un sous-type du type qu’elle attend.

(gen) et (inst) : La r`egle (gen) sert `a introduire le polymorphisme param´etrique dans les types. En effet, elle exprime que si une expression a le type τ sous les contraintes S alors elle a aussi le sch´ema de type ∀χi/S.τ o`u les χisont des variables libres de τ . La r`egle (inst) sert `a instancier les sch´emas de types en types. Pour utiliser cette r`egle, les contraintes du sch´ema de type doivent avoir une solution.

(let) : Le let-polymorphisme est obtenu en appliquant la r`egle (gen) juste apr`es la r`egle (let). Les r`egles (trans) et (trans all) n´ecessitent plus d’explications. Dans ces r`egles nous utilisons les deux fonctions d´efinies ci-dessous. La fonction Comp s’applique `a un type τ et `a un motif m et renvoie un type qui vaudra 0 si le motif ne peut s’appliquer dans une collection de type contenu τ

134 Typage ensembliste Γ ∪ {x : σ}, S ⊢ x : σ (var) Γ ∪ {x : τ1}, S ⊢ e : τ2 Γ, S ⊢ λx.e : τ1 → τ2 (f un) Γ, S ⊢ c : T C(c) (const) Γ, S ⊢ e1 : τ1 → τ 1 Γ, S ⊢ e2: τ2 Γ, S ∪ {τ2⊆ τ1} ⊢ e1 e2 : τ1 (app) Γ, S ⊢ e : τ et Sol (S) 6= ∅ et χ1, . . . , χn non libres dans Γ

Γ, ∅ ⊢ e : ∀χ1, . . . , χn/S.τ (gen) Γ, S ⊢ e : ∀α1, . . . , αn, θ1, . . . , θm/S.τ Γ, S ∪ Sii, ρjj] ⊢ e : τ [τii, ρjj] (inst) Γ, S ⊢ e1 : σ Γ ∪ {x : σ}, S ⊢ e2: τ Γ, S ⊢ let x = e1 in e2 : τ (let) Γ ∪ γτ(pi), S ⊢ gi: bool Γ ∪ γτ(pi), S ⊢ ei: [τi]seq (1 ≤ i ≤ n) Γ, S ∪ {τ ⊆ τ} ∪ S ⊢ {p1/g1 ⇒ e1; . . . ; pn/gn⇒ en} : [τ ]ρ → [τ(trans) o`u S est S 1≤i≤ni?Compτ(pi) ⊆ τ}.

La r`egle suivante ne s’applique que lorsque pn est r´eduit `a un identificateur et gn est l’expression true :

Γ ∪ γτ(pi), S ⊢ gi: bool Γ ∪ γτ(pi), S ⊢ ei : [τi]seq (1 ≤ i ≤ n)

Γ, S ∪ S ⊢ {p1/g1⇒ e1; . . . ; pn/gn⇒ en} : [τ ]ρ → [τ(trans all) o`u S est S

1≤i≤n

i?Compτ(pi) ⊆ τ}.

Fig. 2 – R`egles de typage.

et qui vaudra un type diff´erent de 0 sinon. On dira que cette fonction calcule la compatibilit´e du motif m avec le type τ . On d´efinit inductivement Comp par :

Compτ(µ, m) = Compτ(µ)?Compτ(m) Compτ(x) = τ ∩ 1 = τ Compτ(x : b) = τ ∩ b Compτ(x : r) = τ ∩ [1]r Compτ(∗ as x) = τ ∩ 1 = τ Compτ(b∗ as x) = τ ∩ b Compτ(r∗ as x) = τ ∩ [1]r

Par exemple Compτ(x1: int, x2: f loat) = (τ ∩ int) ? (τ ∩ f loat). Ainsi si τ ne contient pas int et f loat ce type vaut 0.

La fonction γ calcule le contexte de typage induit par un motif m sachant que ce motif s’applique `a une collection de type contenu τ . On d´efinit inductivement γ par :

γτ(µ, m) = γτ(µ) ∪ γτ(m) γτ(x) = {x : τ } γτ(x : b) = {x : τ ∩ b} γτ(x : r) = {x : τ ∩ [1]r} γτ(∗ as x) = {x : [τ ]seq} γτ(b∗ as x) = {x : [τ ∩ b]seq} γτ(r∗ as x) = {x : [τ ∩ [1]r]seq}

D´etaillons `a pr´esent les deux r`egles de typage. Pour chaque r`egle de transformation mi/gi⇒ ei , le type contenu de la s´equence ei est τi sachant que la transformation s’applique `a une collection de type contenu τ et en consid´erant le contexte induit par mi. Le type τi?Compτ(mi) vaudra 0 si les conditions de types de mi font que le motif n’a jamais d’instances dans une collection de type contenu τ (incompatibilit´e), il vaudra τi si la r`egle peut s’appliquer (compatibilit´e).

Le type contenu de la collection renvoy´ee doit ˆetre un sur-type de τi?Compτ(mi) pour chaque i, d’o`u les contraintes τi?Compτ(mi) ⊆ τ car si la r`egle peut s’appliquer, la collection renvoy´ee pourra contenir des ´el´ements de type τi.

Par ailleurs lors de l’application d’une transformation sans r`egle attrape-tout, des valeurs peuvent ne pas ˆetre filtr´ees et resteront dans la collection renvoy´ee, d’o`u la contrainte τ ⊆ τ dans (trans). Cette contrainte est la seule diff´erence entre les r`egles de typage (trans) et (trans all).

VII.4.1 Exemples

Nous donnons ici trois exemples de typage. Le premier exemple est la d´erivation suivante :

{x : α ∩ int}, ∅ ⊢ [x; 1] : [int]seq (var )

∅, {α ⊆ α, (int?(α ∩ int)) ⊆ α} ⊢ {x : int ⇒ [x; 1]} : [α]θ → [α]θ (trans) ∅, ∅ ⊢ {x : int ⇒ [x; 1]} : ∀α, θ/{α ⊆ α, (int?(α ∩ int)) ⊆ α}.[α]θ → [α]θ (gen)

Ici, l’ensemble de contraintes du sch´ema se r´eduit `a ∅. En effet, on peut montrer que (int?(α ∩ int)) ⊆ α est toujours vrai. Donc n’importe quelle instanciation de α et θ convient. Passons au second exemple :

. . .

{x : α ∩ int}, ∅ ⊢ [true] : [bool]seq

. . .

{x : α ∩ int}, ∅ ⊢ x > 0 : int

∅, {α ⊆ β, (bool?(α ∩ int)) ⊆ β} ⊢ {x : int/x > 0 ⇒ [true]} : [α]θ → [β]θ (trans)

∅, ∅ ⊢ {x : int/x > 0 ⇒ [true]} : ∀α, β, θ/{α ⊆ β, (bool?(α ∩ int)) ⊆ β}.[α]θ → [β]θ (gen) Ici le type α ∪ (bool ?(α ∩ int)) est la plus petite instanciation de β v´erifiant les contraintes du sch´ema. Le type suivant est donc valable pour cette transformation : [α]θ → [α ∪ (bool ?(α ∩ int))]θ.

Sans l’utilisation de types conditionnels, le type le plus pr´ecis pour cette transformation aurait ´et´e [α]θ → [α ∪ bool]θ qui porte moins d’informations que le type pr´ec´edent.

Enfin on peut montrer que la transformation {x : int ⇒ [true] ; x ⇒ [false]} a le type [α]θ → [bool ]θ en utilisant la r`egle (trans all) :

136 Typage ensembliste

. . .

{x : α ∩ int}, ∅ ⊢ [true] : [bool]seq

. . .

{x : α}, ∅ ⊢ [false] : [bool]seq

∅, S ⊢ {x : int ⇒ [true] ; x ⇒ [false]} : [α]θ → [bool]θ (trans all )

avec S = {bool ?(α ∩ int) ⊆ bool ; bool ?α ⊆ bool }. Le syst`eme S est toujours vrai car on a toujours τ ?τ ⊆ τ . Donc ∅, ∅ ⊢ {x : int ⇒ [true] ; x ⇒ [false]} : [α]θ → [bool]θ est vrai.

VII.4.2 Propri´et´es

Dans cette section nous ´enon¸cons la propri´et´e de correction du syst`eme de types. On dira qu’un environnement E est correct par rapport `a un contexte Γ et `a une instanciation s des variables de type lorsque E(x) ∈ JΓ(x)Ks pour tout x li´e dans Γ et E.

Lemme 1 (Correction) Soit un typage Γ, S ⊢ e : σ, une solution s de S, un environnement E correct par rapport `a Γ et s portant sur les variables libres de e. Alors Eval (e, E) ∈ JσKs. Id´ee de la preuve. Ceci se montre par induction sur la structure de l’arbre de preuve de typage. Pour toutes les r`egles sauf (trans) et (trans all) c’est assez classique (modulo les sortes). Regardons la r`egle (trans) ou plutˆot une forme simplifi´ee sans les types conditionnels dans les contraintes :

Γ ∪ γτ(pi), S ⊢ gi: bool Γ ∪ γτ(pi), S ⊢ ei: [τi]seq (1 ≤ i ≤ n) Γ, S ∪ {τ ⊆ τ} ∪ S

1≤i≤n

i⊆ τ} ⊢ {p1/g1 ⇒ e1; . . . ; pn/gn⇒ en} : [τ ]ρ → [τ]ρ Il s’agit essentiellement de montrer que si s est une solution de S ∪ {τ ⊆ τ} ∪ S

1≤i≤n

i⊆ τ} et si E est un environnement correct par rapport `a Γ alors la fonction d´enot´ee par Eval (t, E) que nous noterons f est dans J[τ ]ρ → [τ]ρKs. Ceci revient `a montrer que pour toute collection c de J[τ ]ρKs on a f (c) ∈ J[τ]ρKs.

– f ne peut provoquer d’erreur de type car les seules expressions ´evalu´ees par l’application de f sont les gardes et les expressions rempla¸cantes, qui sont bien typ´ees par hypoth`ese d’induction (s est ´egalement une solution de S).

– L’application de la i-`eme r`egle va donner un chemin et une s´equence de J[τi]seqKs. Donc la substitution topologique va retirer certains ´el´ements de la collection c et les remplacer par des ´el´ements de JτiKs. La substitution topologique peut ´egalement lancer une erreur de structure shape.

– Donc la collection renvoy´ee peut contenir des valeurs de la collection initiale et des valeurs d’un JτiKs pour i ≤ n. Donc la collection renvoy´ee est dans J[τ ∪ S

i≤n τi]ρKs. – Or s est solution de {τ ⊆ τ} ∪ S 1≤i≤ni ⊆ τ} donc J[τ ∪ S i≤n τi]ρKs ⊆ J[τ]ρKs. Donc la

collection renvoy´ee est bien dans J[τ]ρKs. ¤

Une preuve compl`ete pour la r`egle (trans) peut ˆetre trouv´ee dans [Coh03a].

Corollaire 1 Si e est un programme (i.e. une expression sans variables libres) et si ∅, ∅ ⊢ e : σ alors Eval (e, ∅) ∈ JσKid, o`u id est la substitution identit´e.

Rappelons qu’`a partir d’une preuve de Γ, S ⊢ e : τ on obtient une preuve de typage de e avec ∅ comme ensemble de contraintes en appliquant la r`egle (gen).

Corollaire 2 Si ∅, ∅ ⊢ e : σ alors Eval (e, ∅) 6= wrong.

Ce dernier corollaire est vrai car la valeur wrong n’appartient `a aucun type. On dira qu’un programme est bien typ´e si il existe un sch´ema de type σ tel que ∅, ∅ ⊢ e : σ. Il est garantit qu’un programme bien typ´e ne provoquera pas d’erreur de type mais, comme nous l’avons d´ej`a ´evoqu´e, on ne sait rien des erreurs de structure. Ce point est discut´e en section VII.10.2 et dans le chapitre VIII.