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).
More generally, you might be interested in https://github.com/ocaml-ppx/ppx_deriving or the fmt
library to write your own printers.
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)
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.