Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

printing expressions of polymorphic type in ocamldebug

Tags:

ocaml

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.

like image 728
lambda.xy.x Avatar asked Mar 23 '15 18:03

lambda.xy.x


1 Answers

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.

Update

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.

like image 108
ivg Avatar answered Sep 30 '22 08:09

ivg