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.