The and
keyword is used either to avoid multiple let
(first example, I never use it for this but why not) or for mutually recursive definitions of types, functions, modules…
As you can see in your second example :
let rec debug stack env (r, ty) = ... | Tunresolved tyl -> o "intersect("; debugl stack env tyl; o ")" ... and debugl stack env x = ... | [x] -> debug stack env x ...
debug
calls debugl
and vice versa. So the and
is allowing that.
[EDIT] It bothered me not to give a proper example so here is one example that you’ll often see :
let rec is_even x = if x = 0 then true else is_odd (x - 1) and is_odd x = if x = 0 then false else is_even (x - 1)
(You can find this example here)
For mutually recursive types, it’s harder to find a configuration but following this wikipedia page we would define trees
and forests
as follow
type 'a tree = Empty | Node of 'a * 'a forest and 'a forest = Nil | Cons of 'a tree * 'a forest
As an example, a forest composed of the empty tree, the singleton tree labeled a
and a two nodes tree with labels b
and c
would then be represented as :
let f1 = Cons (Empty, (* Empty tree *) Cons (Node ('a', (* Singleton tree *) Nil), (* End of the first tree *) Cons (Node ('b', (* Tree composed by 'b'... *) Cons (Node ('c', (* and 'c' *) Nil), Nil) ), Nil (* End ot the second tree *) ) ) );;
And the size function (counting the number of nodes in the forest) would be :
let rec size_tree = function | Empty -> 0 | Node (_, f) -> 1 + size_forest f and size_forest = function | Nil -> 0 | Cons (t, f) -> size_tree t + size_forest f
And we get
# size_forest f1;; - : int = 3