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.
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.)