Skip to content

Latest commit

 

History

History
100 lines (72 loc) · 2.71 KB

README_PPX.md

File metadata and controls

100 lines (72 loc) · 2.71 KB

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).

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 references another user-defined type, ppx_irmin will expect the generic for that type to use the standard naming scheme. 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)

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