On 10/18/2016 12:21 PM, Goswin von Brederlow wrote: > You can pass along the outermost to_string to all to_string > functions so they can restart from the outside when they recurse. Yep :) For the record, I got it working like this: In M0: let assert_false _ = assert false type f = { f : 'a. 'a t -> string } let rec to_string : type a b. ?f:f -> a t -> string = fun ?(f = { f = assert_false }) e -> match e with | I i -> "I:" ^ string_of_int i | S s -> "S:" ^ s | P (x, y) -> to_string ~f x ^ to_string ~f y | e -> f.f e In M1: let rec to_string' : type a. a t -> string = function | T t -> to_string ~f:{ f = to_string' } t | x -> to_string ~f:{ f = to_string' } x let to_string = to_string' Cheers, Andre