Option -rectypes
With a compiler option, we can avoid this restriction to objects in cyclic
types.
$ ocamlc -rectypes ...
$ ocamlopt -rectypes ...
$ ocaml -rectypes
If we take up the above examples in a toplevel started with this option, here is
what we get.
# type 'a tree = 'a * 'a tree list ;;
type 'a tree = 'a * 'a tree list
# let rec height = function
(_,[]) -> 1
| (_,sons) -> 1 + (max_list (List.map height sons)) ;;
val height : ('b * 'a list as 'a) -> int = <fun>
The values tree_1, tree_2 and tree_3
previously defined don't have the same type, but they all have a type
compatible with that of height.
# height tree_1 ;;
- : int = 1
# height tree_2 ;;
- : int = 2
# height tree_3 ;;
- : int = 3
The keyword as belongs to the type language, and as such, it can be
used in a type declaration.
Syntax
type nom = typedef as 'var ;;
We can use this syntax to define type tree.
# type 'a tree = ( 'a * 'vertex list ) as 'vertex ;;
type 'a tree = 'a * 'a tree list
Warning
If this mode may be useful in some cases, it tends to accept the typing of too
many values, giving them types that are not easy to read.
Without the option -rectypes, the function below would have been rejected
by the typing system.
# let inclus l1 l2 =
let rec mem x = function
[] -> false
| a::l -> (l=x) || (mem x a) (* an error on purpose: a and l inverted *)
in List.for_all (fun x -> mem x l2) l1 ;;
val inclus : ('a list as 'a) list list -> ('b list as 'b) -> bool = <fun>
Although a quick examination of the type allows to conclude to an error, we no
longer have an error message to help us locating this error.