package irmin

  1. Overview
  2. Docs
Legend:
Page
Library
Module
Module type
Parameter
Class
Class type
Source

ppx_irmin

PPX extension for automatically generating Irmin generics.

Overview

ppx_irmin automatically generates Irmin generics (values of type _ Irmin.Type.t) corresponding to type declarations in your code. For example:

type tree =
  | Branch of tree * bool option * tree
  | Leaf of int32 * string [@@deriving irmin]

will be expanded to:

type tree = (* as above *)

let tree_t =
  let open Irmin.Type in
  mu (fun tree_t ->
      variant "tree" (fun branch leaf -> function
          | Branch (x1, x2, x3) -> branch (x1, x2, x3)
          | Leaf   (x1, x2)     -> leaf (x1, x2))
      |~ case1 "Branch" (triple tree_t (option bool) tree_t) (fun (x1, x2, x3) -> Branch (x1, x2, x3))
      |~ case1 "Leaf"   (pair int32 string)                  (fun (x1, x2) -> Leaf (x1, x2))
      |> sealv)

Installation and usage

ppx_irmin may be installed via opam:

opam install ppx_irmin

If you're using the dune build system, add the following field to your library, executable or test stanza:

(preprocess (pps ppx_irmin))

You can now use [@@deriving irmin] after a type declaration in your code to automatically derive an Irmin generic with the same name.

Specifics

ppx_irmin supports all of the type combinators exposed in the Irmin.Type module (basic types, records, variants (plain and closed polymorphic), recursive types etc.). Irmin does not currently support higher-kinded generics: all Irmin types must fully grounded (no polymorphic type variables).

To supply base representations from a module other than Irmin.Type (such as when Irmin.Type is aliased to a different module path), the lib argument can be passed to @@deriving irmin:

type foo = unit [@@deriving irmin { lib = Some "Mylib.Types" }]

(* generates the value *)
val foo_t = Mylib.Types.unit
Naming scheme

The generated generics will be called <type-name>_t, unless the type-name is t, in which case the generic is simply t. This behaviour can be overridden using the name argument, as in:

type foo = string list * int32 [@@deriving irmin { name = "foo_generic" }]

(* generates the value *)
val foo_generic = Irmin.Type.(pair (list string) int32)

If the type contains an abstract type, ppx_irmin will expect to find a corresponding generic using its own naming rules. This can be overridden using the [@generic ...] attribute, as in:

type bar = (foo [@generic foo_generic], string) result [@@deriving irmin]

(* generates the value *)
val bar_t = Irmin.Type.(result foo_generic string)

Built-in abstract types such as unit are assumed to be represented in Irmin.Type. This behaviour can be overridden with the [@nobuiltin] attribute:

type t = unit [@nobuiltin] [@@deriving irmin]

(* generates the value *)
let t = unit_t (* not [Irmin.Type.unit] *)
Signature type definitions

The ppx_irmin deriver can also be used in signatures to expose the auto-generated value:

module Contents : sig
  type t = int32 [@@deriving irmin]

  (* exposes generic in signature *)
  val t : t Irmin.Type.t

end = struct
  type t = int32 [@@deriving irmin]

  (* generates generic value *)
  val t = Irmin.Type.int32
end
OCaml

Innovation. Community. Security.