Let's say we have a polymorphic function we'd like to debug, for example:
let rec rev lst = match lst with
| [] -> []
| x::xs -> List.append (rev xs) [x]
To make a program out of it, we add a main function:
let () = ignore (rev [1;2;3;4])
The result is irrelevant, but note rev is called with an int list i.e. a non-polymorphic type.
Still when I debug the execution in ocamldebug, I only get a generic list when i print the list argument:
(ocd) break @ Rev 1
(ocd) run
Breakpoint: 1
1 let rec rev lst = <|b|>match lst with
(ocd) print lst
lst: 'a list = [<poly>; <poly>; <poly>; <poly>]
I know there is no pure (i.e. non camlp4) way to have a generic print function, but does this restriction also hold for ocamldebug? In other words: Is it possible to obtain the list [1;2;3;4]
instead of the <poly>
s in the debugger?
edit:
User ivg proposed to install a printing function of the appropriate type via #install_printer
. I created a new module pp with the following functions:
let rec pplist ch fmt = function
| [] -> ()
| x::xs ->
Format.fprintf ch "%s; " (fmt x);
pplist ch fmt xs
let int_list ch = pplist ch string_of_int
The toplevel reports the type correctly as Format.formatter -> int list -> unit
. The ocamldebug session now looks as follows:
(ocd) load_printer pp.cmo
File ./pp.cmo loaded
(ocd) install_printer Pp.int_list
(ocd) break @ Rev 1
Loading program... done.
Breakpoint 1 at 14768 : file rev.ml, line 1, characters 19-84
(ocd)
(ocd) run
Time : 12 - pc : 14768 - module Rev
Breakpoint : 1
1 let rec rev lst = <|b|>match lst with
(ocd) print lst
lst : 'a list = [<poly>; <poly>; <poly>; <poly>]
But it seems that ocamldebug does not use int_list
and needs a polymorphic 'a list
.
You can install user printers the same way, as you do this in a toplevel. The command in named install_printer
and is described in the Manual. For example, if your element type is abstract, but provides a to_string
function, you can write the printer for it:
let pp ch x = Format.fprintf ch "%s" (to_string x)
And then install the printer with the above mentioned directive.
The above will only you to print concrete types. Abstract values cannot be print. The only way is to restrict them (temporary) to concrete type:
Given a constraint program:
let rec rev lst : int list = match lst with
| [] -> []
| x::xs -> List.append (rev xs) [x]
The ocd will print the list:
Loading program... done.
Breakpoint 1 at 21448: file test.ml, line 1, characters 30-95
(ocd) run
Time: 12 - pc: 21448 - module Test
Breakpoint: 1
1 let rec rev lst : int list = <|b|>match lst with
(ocd) p lst
lst: int list = [1; 2; 3]
The trick with installing a printer will save you from abstract types, not polymorphic.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With