Easy utop-ready formatters, especially for Jane Street data structures?

I’m working on a project where I have lots of sets of strings, and it’s a bit hard to use the REPL because they just show up as <abstr> until I manually convert them to lists. I see that I can specify a custom formatter for a given type by the #install_printer directive, but that requires that I already have a formatter for the desired data type. Before I look into writing one myself, I’m wondering if it already exits in some part of Core Kernel that I haven’t found yet, or if there’s a better way to approach this problem.

Some modules, like Int and String, have such functions (called pp, e.g., Int.pp), but many others (e.g., Map, Bool) do not. Not sure why.

Most of the data structures in Core (and Base) do have sexp-based (de-)serialization functions, though, so you could ostensibly write a small shim to convert first to a sexp, then pretty-print the sexp (using one of the Sexp pretty-printing functions here).

1 Like

More generally, you might be interested in https://github.com/ocaml-ppx/ppx_deriving or the fmt library to write your own printers.

2 Likes

If you’re using base and [@@deriving sexp] when definng your custom types, you can use [%sexp] as a pretty-printer.

utop # [%sexp (s : Set.M(String).t)];;
- : Sexp.t = (one three two)

A lot of types in Base/Core_kernel/Core have these predefined, but as I understand it, there’s no good way to do this generically for polymorphic types like Set. But you can register a printer for a specific such type.

utop # let format_set fmt s = Caml.Format.pp_print_string fmt (Sexp.to_string_hum [%sexp (s : Set.M(String).t)]);;
val format_set : Format.formatter -> (string, 'a) Set.t -> unit = <fun>
utop # #install_printer format_set;;
utop # Set.of_list (module String) ["one";"two";"three"];;
- : (string, String.comparator_witness) Set.t = (one three two)
2 Likes

Thanks everyone for the responses. I didn’t know about Sexp's pretty-printing functions or the [%sexp] syntax extension, and those are both useful.

Seeing as utop is already inferring the type in order to find a printer, it seems like it would be neat if it could be extended to try using [%sexp] with that type (or some other chosen deriver), but if it’s not currently possible then that’s also good to know.