Home

Awesome

Tpf — minimalist datatype-generic programming

%%VERSION%%

Tagless/trivial polytypic functions (Tpf) is a simple and idiomatic library for datatype-generic programming in OCaml.

Generic programming is all about not writing the same old equal again.

Datatype-generic (or polytypic) programming is solving this at the language level.

Tpf allows you to write functions that work on a wide range of unrelated data types. Such functions require only the base language, need no runtime, and seamlessly interoperate with the rest of OCaml. Tpf works in the same stage as the rest of your program, and doesn't rely on meta-programming.

Tpf is closely related to other well-known datatype-generic approaches. It shares the underlying data model with SYB, and uses the spiny encoding. This is a manifest representation, like the one GHC.Generics use. It arises as an adaptation of approaches like these to a language without overloading, giving it an idiomatic flavor, and lending the name.

Tpf has no dependencies and is distributed under the ISC license.

Installation

Tpf can be installed with opam:

opam install tpf
opam install tpf-ext       # Install the optional support for third-party libs
opam install tpf-deriving  # Install the optional PPX deriver

If you don't use opam consult the tpf.opam file for build instructions.

Documentation

The documentation and API reference is automatically generated by odoc from the interfaces. It can be consulted online.

Library layout

Tpf contains several optional libraries and sub-libraries:

Quick start

Consult the quick start section of the documentation.

Performance

Tpf is glacially slow...

You can write a generic function that, for example, counts the number of recursive occurrences, and use this function to measure the length of a list.

It takes about 5x the time it takes List.length.

Of course it does. List.length compiles to a 4-instruction loop. The Tpf version reconstructs the entire list (albeit lazily), and explores every field of every block in it.

... and Tpf is lightning fast!

If you use the industry-leading PPX-based Sexplib deriver, ppx_sexp_conv, and compare the performance of derived conversion functions (sexp_of_tweedledum / tweedledum_of_sexp) to the performance of a Tpf-based generic version, the ratio is about 1.25. Generic version is 25% slower.

If you compose these conversion functions with something that interacts with the actual bytes, the overall performance hit of using generics drops to just below 10%.

Incidentally, most attempts at writing a generic printer will end up being faster than hand-written printers, as CamlinternalFormat.make_printf is a formidable opponent.

Tpf is usable.

Clearly, whether the overhead introduced by generic functions is significant depends entirely on what they are doing. And whether this ends up being prohibitive, depends entirely on your use-case.

It doesn't cost much to try.

Compared to alternatives

PPX deriving

The use cases of ppx_deriving overlap with those of Tpf, even if the two approaches are meant to do different things.

OCaml SYB

(As seen here.)

Generic programming in OCaml

(As seen here.)

Tpf is tagless. It strictly avoids type reflection, which leads to a number of differences that make Tpf feel more natural to an OCaml programmer.