Au niveau du système de module, des annotations de types sont nécessaires pour les arguments des foncteurs:
moduleF(X:sigtypetend(* ← ceci est une annotation de type *))=structincludeXend(* mais le type (i.e. la signature) de retour est inferré *)
Les modules récursifs eux ont besoin d'être totalement annoté, par exemple:
modulerecM:(* ↓ annotation du type de M *)sigtypet=AofS.tvalcompare:t->t->intend=structletcompare=comparetypet=AofS.tendandS:(Set.Swithtypeelt=M.t)(* ← annotation du type de S *)=Set.Make(M);;
Ce besoin d'annotation pour les modules peut se propager dans les fonctions à cause
des modules locaux (ou de première classe).
letdedup(typea(* ←soit un type a abstrait*))l=(* ici on a besoin d'introduire un type a pour le module S définit ci-dessous *)letmoduleS=Set.Make(structtypet=aletcompare=compareend)inS.elements@@S.of_listl
Un autre cas classique d'annotation explicite apparaît pour la récursion polymorphique
sur les types récursifs non homogènes:
type'aarbre_complet=Feuilleof'a|Noeudof('a*'a)arbre_completletrechauteur:'a.(*← ∀a *)'aarbre_complet->int=function|Feuille_->0|Noeuda->(* dans cette branche, hauteur est appliqué à ('a * 'a) arbre_complet *)1+hauteura
Dans ce cas, l'annotation 'a.'a arbre_complet -> int qui équivaut à forall 'a....
est nécessaire car le type du paramètre 'a à l'intérieur de la définition de hauteur et à l'extérieur diffère.
Pour le polymorphisme de second ordre, OCaml ne supporte pas directement les annotations forall à l'intérieur des arguments de fonctions, il faut donc passer soit par des types enregistrements(records):
typeid={f:'a.'a->'a}
ce qui est plus contraignant qu'une annotation directe, soit par le système objet
letpair(id:<f:'a.'a->'a>)=id#f1,id#f[]
Sans cette annotation le typeur va essayer d'unifier le type de 1 et [] et renvoyer une erreur.
Les GADTs de leur côté sont toujours lourds en annotations en Haskell ou OCaml
type'amonoid=|R:floatmonoid|N:intmonoid|Pair:'amonoid*'bmonoid->('a*'b)monoidletreczero:typea.(*← ∀a, a abstrait *)amonoid->a=function|R->0.(* ← dans cette branche, a = float *)|N->0(* ← a = int *)|Pair(a,b)->zeroa,zerob(* a = b * c *)
Enfin, une particularité d'OCaml du aux effets de bords, ce sont les types faiblement polymorphiques, qui ne peuvent pas être exporté par une unité de compilation, ce qui peut nécessiter d'ajouter des annotations de type pour les éliminer. Par exemple, un fichier a.ml
[^] # Re: Un peu déçu par Rust
Posté par octachron . En réponse au journal Un print(1 + "3a"), ça nous inspire comment ?. Évalué à 3.
Au niveau du système de module, des annotations de types sont nécessaires pour les arguments des foncteurs:
Les modules récursifs eux ont besoin d'être totalement annoté, par exemple:
Ce besoin d'annotation pour les modules peut se propager dans les fonctions à cause
des modules locaux (ou de première classe).
Un autre cas classique d'annotation explicite apparaît pour la récursion polymorphique
sur les types récursifs non homogènes:
Dans ce cas, l'annotation
'a.'a arbre_complet -> intqui équivaut àforall 'a....est nécessaire car le type du paramètre
'aà l'intérieur de la définition dehauteuret à l'extérieur diffère.Pour le polymorphisme de second ordre, OCaml ne supporte pas directement les annotations
forallà l'intérieur des arguments de fonctions, il faut donc passer soit par des types enregistrements(records):ce qui est plus contraignant qu'une annotation directe, soit par le système objet
Sans cette annotation le typeur va essayer d'unifier le type de
1et[]et renvoyer une erreur.Les GADTs de leur côté sont toujours lourds en annotations en Haskell ou OCaml
Enfin, une particularité d'OCaml du aux effets de bords, ce sont les types faiblement polymorphiques, qui ne peuvent pas être exporté par une unité de compilation, ce qui peut nécessiter d'ajouter des annotations de type pour les éliminer. Par exemple, un fichier
a.mlne compile pas sans son annotation de type.