PPX extension for automatically generating Irmin type representations.
ppx_irmin
automatically generates Irmin type representations (values of type
_ Irmin.Type.t
) corresponding to type declarations in your code. For example:
type 'a tree =
| Branch of tree * bool option * tree
| Leaf of 'a [@@deriving irmin]
will be expanded to:
type 'a tree = (* as above *)
let tree_t leaf_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 -> leaf x1
|~ case1 "Branch" (triple tree_t (option bool) tree_t) (fun (x1, x2, x3) -> Branch (x1, x2, x3))
|~ case1 "Leaf" leaf_t (fun x1 -> Leaf x1)
|> sealv)
Type representations can also be derived inline using the [%typ: <core-type>]
extension point.
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 type representation with the same name.
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.).
Types with parameters will result in parameterised representations (i.e. type
'a t
is generated a representation of type 'a Type.t -> 'a t Type.t
).
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
This argument can also be passed as a command-line option (i.e. --lib Mylib.Types
, with --lib ''
interpreted as the current module).
The generated type representation will be called <type-name>_t
, unless the
type-name is t
, in which case the representation is simply t
. This
behaviour can be overridden using the name
argument, as in:
type foo = string list * int32 [@@deriving irmin { name = "foo_repr" }]
(* generates the value *)
val foo_repr = Irmin.Type.(pair (list string) int32)
If the type contains an abstract type, ppx_irmin
will expect to find a
corresponding type representation using its own naming rules. This can be
overridden using the [@repr ...]
attribute, as in:
type bar = (foo [@repr foo_repr], string) result [@@deriving irmin]
(* generates the value *)
val bar_t = Irmin.Type.(result foo_repr 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] *)
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 repr in signature *)
val t : t Irmin.Type.t
end = struct
type t = int32 [@@deriving irmin]
(* generates repr value *)
let t = Irmin.Type.int32
end