Option -rectypes
Il existe une option du compilateur et de la boucle d'interaction qui
permet de lever cette limitation aux objets des types cycliques.
$ ocamlc -rectypes ...
$ ocamlopt -rectypes ...
$ ocaml -rectypes
Si nous reprenons les exemples précédents dans une boucle
d'interaction lancée avec cette option, voici ce qu'on obtient.
# type 'a arbre = 'a * 'a arbre list ;;
type 'a arbre = 'a * 'a arbre list
# let rec hauteur = function
(_,[]) -> 1
| (_,fils) -> 1 + (max_list (List.map hauteur fils)) ;;
val hauteur : ('b * 'a list as 'a) -> int = <fun>
Les valeurs arbre_1, arbre_2 et arbre_3
définies auparavant n'ont pas le même type mais ont toutes un type
compatible avec celui de hauteur.
# hauteur arbre_1 ;;
- : int = 1
# hauteur arbre_2 ;;
- : int = 2
# hauteur arbre_3 ;;
- : int = 3
Le mot clé as fait partie du langage de type, à ce titre il peut être utilisé dans une déclaration de type.
Syntaxe
type nom = typedef as 'var ;;
Nous pouvons définir le type arbre en utilisant cette syntaxe.
# type 'a arbre = ( 'a * 'sommet list ) as 'sommet ;;
type 'a arbre = 'a * 'a arbre list
Warning
Si ce mode peut se révéler utile en quelques occasions, il a
tendance à accepter le typage de trop de valeurs en leur donnant des
types difficiles à lire.
Sans l'option -rectypes, la fonction suivante aurait été rejetée
par le typeur.
# let inclus l1 l2 =
let rec mem x = function
[] -> false
| a::l -> (l=x) || (mem x a) (* erreur volontaire : inversion de a et l *)
in List.for_all (fun x -> mem x l2) l1 ;;
val inclus : ('a list as 'a) list list -> ('b list as 'b) -> bool = <fun>
Bien que l'examen du type permet de constater immédiatement qu'il y
a une erreur, il n'y a plus de message d'erreur permettant de
localiser cette erreur.