The OCaml repl ("toplevel") has rich printing for any types, user-defined or otherwise. Is it possible to access this functionality outside the toplevel, rather than having to write an entirely custom set of value printers for one's own entire set of types?
-
related: https://discuss.ocaml.org/t/how-does-one-print-any-type/4362/12 – Charlie Parker Jul 18 '21 at 19:01
-
related: quora https://qr.ae/pGu2yI – Charlie Parker Jul 18 '21 at 21:01
-
if you don't know how to print in top level (and looking to print in **ANYWAY** see this: https://discuss.ocaml.org/t/how-does-one-print-any-type/4362/16?u=brando90). Basically load the file in toplevel/utop `#use "file.ml";;` and then call the variable `var;;` in toplevel. – Charlie Parker Jun 24 '22 at 14:57
4 Answers
The pretty-printing facility is part of the toplevel library. You'll find the source in toplevel/genprintval.ml
. It's understandable, considering that it needs type information: you can't just throw any value at it, the choice of pretty-printer is based on the type.
If you want to use this code in your program, you'll need to link with the toplevel library (toplevellib.cma
) or compile in genprintval
(which means bringing in enough bits of the type checker to analyse the type, it can get pretty big).
There is a similar facility (but not sharing the code, I think) in the debugger (debugger/printval.ml
and debugger/loadprinter.ml
).
There are third-party libraries that you can directly link against and that provide pretty-printing facilities. Extlib's Std.dump
provides a very crude facility (not based on the type). Deriving by Jeremy Yallop and Jake Donham is another approach. This Caml Weekly News item offers more suggestions.

- 104,111
- 38
- 209
- 254
-
1@newacct Yes, you need the type information, which is discarded by the compiler (but is available to the toplevel or the debugger). Third-party libraries provide lightweight ways to write a type-specific pretty-printer for every type, not a way to write a generic type-dependent pretty-printer. There are language extensions that permit generics, but no production-ready implementation AFAIK. – Gilles 'SO- stop being evil' Aug 31 '11 at 23:02
-
1btw at present, at least, `Extlib.Std.dump` and `BatPervasives.dump`, mentioned by @newacct, are the same function: `Extlib.Std.dump == BatPervasives.dump;;` => `bool = true`. – Mars May 08 '17 at 06:47
The OCaml Batteries Included library contains the dump
function in its BatPervasives module . It converts any value to a string and returns it. You can see its source code here. The output will not be identical to the toplevel, because some information is lost at runtime, e.g. abstract data type constructors will become integers.

- 119,665
- 29
- 163
- 224
No. As of OCaml 4.06, the compiler doesn't make type information available at runtime. It is therefore not possible to have standalone programs that nicely print any OCaml data without some compromises. The two main avenues are:
- Some form of preprocessing which derives printers from type definitions. Today, the best approach might be the show plugin of ppx-deriving. This requires annotating each type definition.
- Relying only on the runtime representation of values. This requires no effort from the programmer and works out-of-the-box on data produced by external libraries. However it doesn't show things like record field names or any other information that was lost during compilation. An instance of this approach is detailed below.
The function Dum.to_stdout
from the dum package will take any OCaml value, including cyclic ones, and print their physical representation in a human-readable form given the data available at runtime only.
Simple things give more or less what one would expect:
# Dum.to_stdout ("Hello", 42, Some `Thing, [1;2;3]);;
("Hello" 42 (582416334) [ 1 2 3 ])
Cyclic—and in general, shared—values are shown using labels and references. This is a circular list:
# let rec cyc = 1 :: 2 :: cyc;;
# Dum.to_stdout cyc;;
#0: (1 (2 #0))
We can also look into the runtime representation of functions, modules and other things. For example, the Filename
module can be inspected as follows:
# module type Filename = module type of Filename;;
# Dum.to_stdout (module Filename : Filename);;
(
#0: "."
".."
#1: "/"
#2: closure (#1 #3: closure ())
#4: closure ()
closure (#4)
closure ()
closure ()
closure (#5: closure (#3))
closure (#5)
closure (#5)
closure (closure () #3 #0)
closure (closure () #3 #0)
closure (#6: closure (#2 <lazy>) #7: (#8))
closure (#6 #7)
closure (#7)
closure (#7)
#8: "/tmp"
closure (closure () "'\\''")
)

- 4,629
- 2
- 22
- 28
-
-
@CharlieParker with opam like for most ocaml libraries: `opam install dum` – Martin Jambon Jul 21 '21 at 04:01
I know you want it outside of top level but I think it's worth mentioning how to do it in top level so that ppl looking for printing in anyway (since it seems outside top level is not trivial):
- load your file in top level
utop
#use "datatypes.ml";;
- then "call" the variable inside top level:
utop # let nada = Nothing;;
utop # nada;;
- : foo = Nothing
ref: https://discuss.ocaml.org/t/how-does-one-print-any-type/4362/16?u=brando90

- 5,884
- 57
- 198
- 323
-
if you don't know how to print in top level (and looking to print in **ANYWAY** see this: https://discuss.ocaml.org/t/how-does-one-print-any-type/4362/16?u=brando90). Basically load the file in toplevel/utop `#use "file.ml";;` and then call the variable `var;;` in toplevel. – Charlie Parker Jun 24 '22 at 14:57