# Overview of libraries for showing OCaml values

**URL:** <https://discuss.ocaml.org/t/overview-of-libraries-for-showing-ocaml-values/12076>\
**Category:** Ecosystem\
**Created:** [May 2, 2023, 8:50pm UTC](https://discuss.ocaml.org/t/overview-of-libraries-for-showing-ocaml-values/12076 "2023-05-02T20:50:54Z")\
**Posts on this page:** 9\
**Page:** 1

<div class="post-metadata">

**Author:** ![antron](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/antron/32/62_2.png) [@antron](https://discuss.ocaml.org/u/antron)\
**Post date:** [May 2, 2023, 8:50pm UTC](https://discuss.ocaml.org/t/overview-of-libraries-for-showing-ocaml-values/12076/1 "2023-05-02T20:50:54Z")

</div>

In light of the [recent thread](https://discuss.ocaml.org/t/idea-standard-ocaml-runtime-type-representation/12051/2) on, among other things, showing OCaml values, and because of Dream’s [long-standing need](https://github.com/aantron/dream/wiki/Roadmap#logging) for this to exist in OCaml, I’ve done, as [suggested](https://discuss.ocaml.org/t/idea-standard-ocaml-runtime-type-representation/12051/6), a comparison of the available libraries. They seem to fall into three categories.

  

1. Libraries that walk the runtime representation of values and dump it.

  

1. Libraries, such as `ppx_deriving`, that have a PPX generate, or the user manually provide, information about types – that is, provide helper values that describe types, and then ask the user to provide that information to walk values and dump them.

  

1. Libraries that use a PPX at the call site to provide what looks like an `'a -> string` function as in (1), but try to infer the type of the value being shown and derive its printer as in (2).

  

In my opinion, for the needs I see, the best approach would be runtime printing as in (1) with runtime type information that is accessible through pointers or indices stored in OCaml blocks. I wonder if this is what the LexiFi [fork](https://discuss.ocaml.org/t/idea-standard-ocaml-runtime-type-representation/12051/2) does. @nojb?

  

For those interested, we did the main part of the comparison on [stream](https://www.twitch.tv/videos/1809433679?t=00h14m21s).

---

<div class="post-metadata">

**Author:** ![nojb](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/nojb/32/519_2.png) [@nojb](https://discuss.ocaml.org/u/nojb)\
**Post date:** [May 2, 2023, 10:35pm UTC](https://discuss.ocaml.org/t/overview-of-libraries-for-showing-ocaml-values/12076/2 "2023-05-02T22:35:03Z")

</div>

> [@antron](#):
>
> I wonder if this is what the LexiFi [fork](https://discuss.ocaml.org/t/idea-standard-ocaml-runtime-type-representation/12051/2) does. @nojb?

Not exactly.

We don’t attach type information to values directly, as we don’t want to modify the runtime model of OCaml (also, this would only work with heap-allocated values, which would all become larger).

What we do instead is that when a function has a labeled, _non-optional_ argument of type `'a ttype` (here `'a ttype` is the “type of types” with constructors corresponding to each kind of type in OCaml) and the argument is not passed explicitly, then the compiler synthetizes it at each callsite.

Concretely, if we define a function of the form

```auto
let show ~(t: 'a ttype) (x: 'a) : string =
  match t with
  | Int -> string_of_int x
  | String -> x
  | ...

```

And we call it with `show 42`, the compiler inserts `~t:Int` as first argument. For efficiency, type witnesses (the values of type `'a ttype`) are actually computed at compilation-time whenever possible.

Makes sense?

Cheers,  
Nicolas

---

<div class="post-metadata">

**Author:** ![jbeckford](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/jbeckford/32/3027_2.png) [@jbeckford](https://discuss.ocaml.org/u/jbeckford)\
**Post date:** [May 3, 2023, 1:08am UTC](https://discuss.ocaml.org/t/overview-of-libraries-for-showing-ocaml-values/12076/3 "2023-05-03T01:08:02Z")

</div>

Wouldn’t the following be compatible with the standard `ocamlc` compiler _and_ allow for a custom patched compiler that synthesizes `'a ttype` correctly?

```ocaml
let show (type a) ?(t : a ttype option) (x: a) : string =
  match t with
  | None -> Dum.to_string x (* Any printer from @antron's Type 1 *)
  | Some Int -> string_of_int x
  | Some String -> x
  | _ -> "something else"

```

The price is an extra word for `Some _`.

---

<div class="post-metadata">

**Author:** ![sid](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/sid/32/1476_2.png) [@sid](https://discuss.ocaml.org/u/sid)\
**Post date:** [May 3, 2023, 12:01pm UTC](https://discuss.ocaml.org/t/overview-of-libraries-for-showing-ocaml-values/12076/4 "2023-05-03T12:01:57Z")

</div>

You mention you have used this for many years in your lexfi ocaml fork. Sounds like it would be robust, well ironed out by now and deals with the various needs that may have arisen over the years.

How about trying to get it into OCaml – have you tried? Was it not accepted?

---

<div class="post-metadata">

**Author:** ![antron](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/antron/32/62_2.png) [@antron](https://discuss.ocaml.org/u/antron)\
**Post date:** [May 3, 2023, 12:43pm UTC](https://discuss.ocaml.org/t/overview-of-libraries-for-showing-ocaml-values/12076/5 "2023-05-03T12:43:10Z")

</div>

By the way, do we have a link to the actual LexiFi fork?

---

<div class="post-metadata">

**Author:** ![nojb](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/nojb/32/519_2.png) [@nojb](https://discuss.ocaml.org/u/nojb)\
**Post date:** [May 3, 2023, 1:36pm UTC](https://discuss.ocaml.org/t/overview-of-libraries-for-showing-ocaml-values/12076/6 "2023-05-03T13:36:08Z")

</div>

I see there is a lot of enthusiasm for adding some form of type reflection to OCaml; that’s great! It is true that at LexiFi we have a tried-and-tested system in use for a long time. Let me try to give some perspective about it and answer some of the questions that came up:

- The LexiFi patch actually consists of two parts: 1) the representation of types as an OCaml datatype; 2) a patch to the typechecker/middle end to have the compiler automatically generate type witnesses (as sketched [above](https://discuss.ocaml.org/t/overview-of-libraries-for-showing-ocaml-values/12076/2)).

- It is important to note that 1) is to an extent independent of 2); it comes down to giving a suitable definition of the “type of types”. I understand from past discussion that proposals in this direction would be welcome by the OCaml dev team. Accordingly, one should concentrate for the most part in 1) to make progress.

- For historical reasons the LexiFi version of 1) (ie the type representation, see [here](https://github.com/LexiFi/lrt/blob/038ff963bd066c9d94cffb9896b04b6b8696f136/lib/stype.mli#L12-L25) and [here](https://github.com/LexiFi/lrt/blob/038ff963bd066c9d94cffb9896b04b6b8696f136/lib/xtype.mli#L16-L36)) has a number of quirks. Furthermore, it makes design choices that may not be the best ones in general. For example, it only represents closed types: no type constructors or type variables can be represented, and so in particular neither can exotic types such as GADTs, first-class modules, extensible types, polymorphic variants, etc.

- The _main_ challenge in devising a suitable representation of types is deciding how to handle abstract types (see the [paper](https://v2.ocaml.org/meetings/ocaml/2013/proposals/runtime-types.pdf) and the [slides](https://v2.ocaml.org/meetings/ocaml/2013/slides/henry.pdf) I linked to in [the other thread](https://discuss.ocaml.org/t/idea-standard-ocaml-runtime-type-representation/12051/2)). At LexiFi abstract types are represented via “global names” (ie we identify an abstract type `M.t` by its name `"M.t"`). This works reasonably well in practice, but is not a good solution in general (the notion of “name” for an abstract type is not well-defined). I suspect the answer may be something of a research problem…

- LexiFi did discuss upstreaming a version of its fork long time ago (~2011), but I suspect it wasn’t done mainly because of the theoretical shortcomings of the current implementation (eg handling of abstract types).

- Accordingly, the LexiFi fork is not open-source: we don’t have the manpower to support it as an open-source project, we don’t want to release a version of this technology which has known limitations that make it easy to shot yourself in the foot if you don’t know what you are doing, and finally there are some commercial considerations to take into account (but my impression is that if this technology was polished enough that it could be accepted upstream, LexiFi would be happy to do so).

- Personally, from a distance, [GitHub - thierry-martinez/refl: OCaml PPX deriver for reflection](https://github.com/thierry-martinez/refl) looks rather interesting, but its [type representation](https://github.com/thierry-martinez/refl/blob/master/runtime/desc.ml) is quite complex and is not clear it can be made suitable for “practical” use.

I hope this answers some of the questions!

Cheers,  
Nicolas

---

<div class="post-metadata">

**Author:** ![sid](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/sid/32/1476_2.png) [@sid](https://discuss.ocaml.org/u/sid)\
**Post date:** [May 3, 2023, 1:39pm UTC](https://discuss.ocaml.org/t/overview-of-libraries-for-showing-ocaml-values/12076/7 "2023-05-03T13:39:14Z")

</div>

Thanks for the detailed reply – appreciate it!

> [@nojb](#):
>
> Personally, from a distance, [GitHub - thierry-martinez/refl: OCaml PPX deriver for reflection](https://github.com/thierry-martinez/refl) looks rather interesting, but its [type representation](https://github.com/thierry-martinez/refl/blob/master/runtime/desc.ml) is quite complex and is not clear it can be made suitable for “practical” use.

FWIW, I’ve used `refl` and found it quite capable/useful. It worked where other packages failed (though I may have been using the other packages wrong).

---

<div class="post-metadata">

**Author:** ![Frederic\_Loyer](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/frederic_loyer/32/3472_2.png) [@Frederic\_Loyer](https://discuss.ocaml.org/u/Frederic_Loyer)\
**Post date:** [May 3, 2023, 6:20pm UTC](https://discuss.ocaml.org/t/overview-of-libraries-for-showing-ocaml-values/12076/8 "2023-05-03T18:20:50Z")

</div>

I have proposed the collection of links to Awesome OCaml. This seems to be a good place to find easily such gems.

---

<div class="post-metadata">

**Author:** ![samoht](https://sea2.discourse-cdn.com/flex020/user_avatar/discuss.ocaml.org/samoht/32/81_2.png) [@samoht](https://discuss.ocaml.org/u/samoht)\
**Post date:** [May 15, 2023, 9:31am UTC](https://discuss.ocaml.org/t/overview-of-libraries-for-showing-ocaml-values/12076/9 "2023-05-15T09:31:44Z")

</div>

> [@antron](#):
>
> [**repr**](https://mirage.github.io/repr/repr/Repr/index.html#val-pp_json), which appears to have the user build the type representation manually from combinators in addition to also having the user pass it where needed.

Just wanted to add that you can use `ppx_repr` if you don’t want to build those representation manually (but the API has been designed so it’s easy enough to write the record and variant representations manually).
