PPX deriver for dune's Dyn.t
converters
ppx_deriving_dyn
derives basic Dyn.t
converters from type definitions.
Attach the [@@deriving dyn]
attribute to your type definitions to generate
the corresponding to_dyn
function.
It can be used to derive both the function and its signature depending on the context.
For example you can use it in your .ml
files like this:
type t = int
[@@deriving dyn]
to generate the following:
let to_dyn = Dyn.int
or in your .mli
files:
type t
[@@deriving dyn]
to generate the following:
val to_dyn : t Dyn.builder
ppx_deriving_dyn
follows the following rules:
- The converter is named
to_dyn
for types namedt
and<type name>_to_dyn
for any other type name. - It uses the builders provided by
Dyn
for the following base types:unit
char
string
int
int32
int64
nativeint
float
bool
list
array
option
- Tuple types are converted using an inline
(fun (x0, x1, x2, x3) -> Dyn.Tuple [...])
- It uses
Dyn.record
for record types - It uses
Dyn.variant
for variant and polymorphic variant types. Inline record arguments are converted usingDyn.record
as well. - An
'a Dyn.builder
extra argument is expected for each type parameter, following the declaration order, e.g. for atype ('a, 'b) t
it will generateval to_dyn : 'a Dyn.builder -> 'b Dyn.builder -> ('a, 'b) t Dyn.builder
ppx_deriving_dyn
allows you to override the default behaviour using the
following attributes.
It can be used as [@to_dyn ...]
or [@ppx_deriving_dyn.to_dyn ...]
and allows
you to define how a specific part of a type should be converted to a Dyn.t
value by attaching this attribute to it and passing the function to use in the
payload.
Here are some examples on how to use it:
type t = float [@to_dyn special_float_to_dyn]
[@@deriving dyn]
type t = int * string * (bool [@to_dyn fun b -> Dyn.string (string_of_bool b)])
[@@deriving dyn]
type t =
{ a : int
; b : string option
[@to_dyn
function
| Some s -> Dyn.string s
| None -> Dyn.string "null"]
}
[@@deriving dyn]
The attribute can be attached to a core type or record field and accepts function identifier, partial function applications and anonymous functions as payload.
It can be used as [@ignore]
, [@to_dyn.ignore]
or
[@ppx_deriving_dyn.to_dyn.ignore]
and allows you to exclude part of a tuple,
record or variant arguments from the output of derived to_dyn
function.
For example, with the following type definition:
type t = int * (string[@ignore]) * bool
[@@deriving dyn]
The generated dyn converter will ignore the string element of the tuple and
return a Dyn.t
value describing an int * bool
pair. To clarify this a bit,
the generated code will look roughly like this:
let to_dyn (x0, _, x2) = Dyn.Tuple [Dyn.int x0; Dyn.bool x2]
It can also be used to similarly ignore fields of a record:
type t =
{ field_a : int
; field_b : string [@ignore]
; field_c : bool
}
[@@deriving dyn]
which will produce the following dyn converter:
let to_dyn {field_a; field_b = _; field_c} =
Dyn.record
[("field_a", (Dyn.int field_a)); ("field_c", (Dyn.bool field_c))]
Finally, you can use it on sum type constructor or polymorphic variant's arguments:
type t =
| A of int * (string [@ignore])
[@@deriving dyn]
which will produce the following dyn converter:
let to_dyn = function
| A (x0, _) -> Dyn.variant "A" [Dyn.int x0]
Note that you cannot ignore all elements of a tuple or all fields of a record
but you can ignore all arguments of a constructor, in which case the to_dyn
function will treat it as if it had no argument, e.g.:
type t =
| A of (int[@ignore])
[@@deriving dyn]
will derive:
let to_dyn = function
| A _ -> Dyn.variant "A" []
It is also worth noting that if you ignore all elements of a tuple but one, the dyn converter will treat it as it was just that type and not as a tuple anymore, e.g.:
type t = int * (string [@ignore])
[@@deriving dyn]
will derive:
let to_dyn (x0, _) = Dyn.int x0
This attribute can be used only in very specific places so it's easy to misuse
it if you forget to add the right brackets. If you're having trouble with it, we
recommend you add -check
to your dune file's (pps ...)
field. This will
enable some ppxlib driver's check including one reporting unused attributes.
It should help you debug issues with [@ignore]
as a misplaced one is likely
not to be consumed by ppx_deriving_dyn
and therefore reported as such by the
driver when building your project.