Is there a way to print user-defined datatypes?
Asked Answered
K

5

18

I can't use print_endline because it requires a string, and I don't (think) I have any way to convert my very simple user-defined datatypes to strings. How can I check the values of variables of these datatypes?

Katharinakatharine answered 22/9, 2011 at 17:11 Comment(2)
#7442949Distich
https://mcmap.net/q/740483/-ocaml-get-value-39-s-type-nameDistich
P
15

In many cases, it's not hard to write your own string_of_ conversion routine. That's a simple alternative that doesn't require any extra libraries or non-standard OCaml extensions. For the courses I teach that use OCaml, this is often the simplest mechanism for students.

(It would be nice if there were support for a generic conversion to strings though; perhaps the OCaml deriving stuff will catch on.)

Phyllis answered 23/9, 2011 at 23:30 Comment(0)
B
10

There's nothing in the base language that does this for you. There is a project named OCaml Deriving (named after a feature of Haskell) that can automatically derive print functions from type declarations. I haven't used it, but it sounds excellent.

http://code.google.com/p/deriving/

Once you have a function for printing your type (derived or not), you can install it in the ocaml top-level. This can be handy, as the built-in top-level printing sometimes doesn't do quite what you want. To do this, use the #install-printer directive, described in Chapter 9 of the OCaml Manual.

Bertie answered 22/9, 2011 at 18:1 Comment(0)
S
4

There are third-party library functions like dump in OCaml Batteries Included or OCaml Extlib, that will generically convert any value to a string using all the runtime information it can get. But this won't be able to recover all information; for example, constructor names are lost and become just integers, so it will not look exactly the way you want. You will basically have to write your own conversion functions, or use some tool that will write them for you.

Sowens answered 22/9, 2011 at 21:2 Comment(0)
B
2

Along the lines of previous answers, ppx_sexp is a PPX for generating printers from type definitions. Here's an example of how to use it while using jbuilder as your build system, and using Base and Stdio as your stdlib.

First, the jbuild file which specifies how to do the build:

(jbuild_version 1)

(executables
 ((names (w))
  (libraries (base stdio))
  (preprocess (pps (ppx_jane ppx_driver.runner)))
  ))

And here's the code.

open Base
open Stdio

type t = { a: int; b: float * float }
[@@deriving sexp]

let () =
  let x = { a = 3; b = (4.5,5.6) } in
  [%sexp (x : t)] |> Sexp.to_string_hum |> print_endline

And when you run it you get this output:

((a 3) (b (4.5 5.6)))

S-expression converters are present throughout Base and all the related libraries (Stdio, Core_kernel, Core, Async, Incremental, etc.), and so you can pretty much count on being able to serialize any data structure you encounter there, as well as anything you define on your own.

Bobbe answered 19/11, 2017 at 20:33 Comment(0)
C
0

Perhaps beyond the scope of this question, but one might also use a customer formatter with Format.printf. Consider a simple example:

module Foo = struct
  type t = Foo of int * int

  let pp ppf (Foo (a, b)) =
    Format.fprintf ppf "(%d, %d)" a b
end

And then we might print a value of type Foo.foo with:

# Format.printf "%a\n" Foo.pp @@ Foo.Foo (27, 42);;
(27, 42)
- : unit = ()

This has the advantage that it can readily be used to also generate a string.

# Format.asprintf "%a" Foo.pp @@ Foo.Foo (27, 42);;
- : string = "(27, 42)"
Caralie answered 12/4, 2023 at 22:17 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.