Search code examples
debuggingocamlpretty-print

How to print an abstract data type within in a functor in ocamldebug


I am struggling with how to install a printer function for a type used inside a functor. The structure looks a little like this:

module Input : sig
   type t
   val print fmt arg : Format.formatter -> t -> unit
end

module type INPUT = module type of Input

module F (I:INPUT) : sig
   val foo : I.t -> unit
end

Now i want to print the value of type Input.t used in F.foo. I can successfully install a printer for Input.t using load_printer and install_printer Input.print but it does not recognize that the type is the right one when printing from inside F (Input).

As requested here is a self contained example. It should be built with debugging turned on and then the .cmo should be loaded with load_printer in the debugger.

module type INPUT = sig
  type t
  val print : Format.formatter -> t -> unit
  val to_list : t -> int list
  val of_list :  int list -> t
end

module V1 : INPUT = struct
  type t = int
  let print fmt i = Format.fprintf fmt "%d" i
  let to_list i = [i]
  let of_list = function [i] -> i | _ -> raise @@ Failure ""
end

module V2 : INPUT = struct
  type t = int * int
  let print fmt (i, j) = Format.fprintf fmt "%d, %d" i j
  let to_list (i, j) = [i; j]
  let of_list = function [i; j] -> (i, j) | _ -> raise @@ Failure ""
end

module F (V:INPUT) = struct
  let ssquare v = (V.to_list v)
                |> List.map (fun i -> i * i)
                |> List.fold_left (+) 0
  let print fmt v =
    let open Format in
    print_string "<";
    V.to_list v |> List.iter print_int;
    print_string ">"
end

module F2 = F (V2);;

let v2 = V2.of_list [2;4] in
let _ = Format.fprintf Format.std_formatter "%a\n" F2.print v2 in
let _ = F2.ssquare v2 in
()

This program prints the value v2 just fine. However there are actually two problems when debugging. I can install_printer V2.print, but when placing the debugger in the ssquare function and invoking print v2 this does not print it. Furthermore, I don't know how I would even install the print defined in the functor.


Solution

  • It seems to me there's no way to do what you want. One way to look at this is that ocamldebug matches print functions by type. But ocamldebug considers the type of the value v that you want to print to be V.t, and V is a formal parameter of the functor F. There's no way (that I can think of) to make a function that accepts this type. The function F.print would seem to be a candidate, but it's not an actual function until you instantiate the functor. And the type accepted by the print function in the instantiated functor is no longer V.t.

    For example, ocamldebug considers the type accepted by F2.print to be V2.t:

    (ocd) print N.F2.print
    N.F2.print: 'a -> N.V2.t -> unit = <fun>
    

    It would be great if there were ways to do things like this, possibly by enriching the way that ocamldebug chooses the printer for a value. But it also sounds kind of hairy.

    (Sorry I couldn't be more helpful, but as I said it's telling that this question gets asked but never answered.)