(* the OO-like interface we will meet two different ways *) type t = { cons : int -> t; decons : unit -> ((int * t) option); length : unit -> int } (* way #1, "methods" use "private fields" i and l *) let rec cons_f i l = let rec r = { cons = (fun j -> cons_f j r); decons = (fun () -> Some (i,l)); length = (fun () -> 1 + l.length ()) } in r let mt_list1 = let rec r = { cons = (fun j -> cons_f j r); decons = (fun () -> None); length = (fun () -> 0) } in r (* way #2, "methods" use "private fields" l and len *) (* faster length, slower cons *) let rec make l = let len = List.length l in { cons = (fun i -> make (i::l)); decons = (fun () -> match l with [] -> None | hd::tl -> Some(hd,make tl)); length = (fun () -> len) } let mt_list2 = make [] let lst = [mt_list1; mt_list2; mt_list1.cons(7); mt_list2.cons(9)] type t2 = { (* impossible to implement correctly *) cons : int -> t2; average : unit -> int; append : t2 -> t2 }