{"id":13726303,"url":"https://github.com/ocaml-ppx/ppx_deriving","last_synced_at":"2025-12-18T05:48:42.772Z","repository":{"id":18694004,"uuid":"21903854","full_name":"ocaml-ppx/ppx_deriving","owner":"ocaml-ppx","description":"Type-driven code generation for OCaml","archived":false,"fork":false,"pushed_at":"2025-03-17T08:56:07.000Z","size":1543,"stargazers_count":484,"open_issues_count":42,"forks_count":91,"subscribers_count":17,"default_branch":"master","last_synced_at":"2025-05-12T21:54:19.217Z","etag":null,"topics":["deriving"],"latest_commit_sha":null,"homepage":"","language":"OCaml","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ocaml-ppx.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2014-07-16T14:23:15.000Z","updated_at":"2025-05-12T00:43:56.000Z","dependencies_parsed_at":"2024-03-14T17:59:32.870Z","dependency_job_id":"7b86d4e7-6832-4c30-b58c-838535e18f70","html_url":"https://github.com/ocaml-ppx/ppx_deriving","commit_stats":{"total_commits":411,"total_committers":50,"mean_commits":8.22,"dds":0.5815085158150852,"last_synced_commit":"b4896214b047dc750184feb474331e2ba626f2b1"},"previous_names":[],"tags_count":32,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ocaml-ppx%2Fppx_deriving","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ocaml-ppx%2Fppx_deriving/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ocaml-ppx%2Fppx_deriving/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ocaml-ppx%2Fppx_deriving/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ocaml-ppx","download_url":"https://codeload.github.com/ocaml-ppx/ppx_deriving/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254328385,"owners_count":22052632,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["deriving"],"created_at":"2024-08-03T01:02:58.623Z","updated_at":"2025-12-18T05:48:42.693Z","avatar_url":"https://github.com/ocaml-ppx.png","language":"OCaml","funding_links":[],"categories":["OCaml","Printers helpers"],"sub_categories":[],"readme":"[@@deriving]\n============\n\n_deriving_ is a library simplifying type-driven code generation on OCaml.\n\n_deriving_ includes a set of useful plugins:\n\n- [show][]\n- [eq][]\n- [ord][eq]\n- [enum][]\n- [iter][]\n- [map][iter]\n- [fold][iter]\n- [make][] (`create` also exists, but it remains solely for backwards compatibility)\n- [yojson][]\n- [protobuf][]\n\nSponsored by [Evil Martians](http://evilmartians.com).\n\n[show]: #plugin-show\n[eq]: #plugins-eq-and-ord\n[enum]: #plugin-enum\n[iter]: #plugins-iter-map-and-fold\n[make]: #plugin-make\n[yojson]: https://github.com/ocaml-ppx/ppx_deriving_yojson#usage\n[protobuf]: https://github.com/ocaml-ppx/ppx_deriving_protobuf#usage\n\n**Note:** since _deriving_ was released by whitequark in 2014, the OCaml ppx ecosystem has changed a lot. For new projects wishing to create a new deriving plugin, we recommend using [ppxlib](https://github.com/ocaml-ppx/ppxlib) directly. The module [Ppxlib.Deriving](https://ocaml-ppx.github.io/ppxlib/ppxlib/Ppxlib/Deriving/index.html) provide functionality similar to _deriving_, better integrated with ppxlib, and offers a nicer API in some places. _deriving_ is still maintained to keep existing plugins working as well as possible. Although note that the above deprecation note only covers the API and not the plugins (e.g. `ppx_deriving.show`, `ppx_deriving.eq`, ...).\n\nInstallation\n------------\n\n_deriving_ can be installed via [OPAM](https://opam.ocaml.org):\n\n    opam install ppx_deriving\n\nBuildsystem integration\n-----------------------\n\nTo use _deriving_, only one modification is needed: you need to require via ocamlfind the package corresponding to the _deriving_ plugin. This will both engage the syntax extension and link in the runtime components of the _deriving_ plugin, if any.\n\nFor example, if you are using ocamlbuild, add the following to `_tags` to use the default _deriving_ plugins:\n\n    \u003csrc/*\u003e: package(ppx_deriving.std)\n\nWith Dune, you should add a `preprocess` directive to your target:\n\n    (executable\n      (libraries whatever)\n      (preprocess (pps ppx_deriving.show ppx_deriving.ord))\n      (name blah))\n\nDune's `pps` directive allows faster preprocessing by linking the specified preprocessors into a single executable (documented [here](https://readthedocs.org/projects/dune/downloads/pdf/latest/#subsection.5.7.2)). This can significantly speed up compilation on large projects which use many derivers.\n\n\nIf you are using another buildsystem, just make sure it passes `-package ppx_deriving.whatever` to ocamlfind.\n\nUsage\n-----\n\nFrom a user's perspective, _deriving_ is triggered by a `[@@deriving plugin]` annotation attached to a type declaration in structure or signature:\n\n``` ocaml\ntype point2d = float * float\n[@@deriving show]\n```\n\nIt's possible to invoke several plugins by separating their names with commas:\n\n``` ocaml\ntype point3d = float * float * float\n[@@deriving show, eq]\n```\n\nIt's possible to pass options to a plugin by appending a record to plugin's name:\n\n``` ocaml\ntype t = string\n[@@deriving yojson { strict = true }]\n```\n\nIt's possible to make _deriving_ ignore a missing plugin rather than raising an error by passing an `optional = true` option, for example, to enable conditional compilation:\n\n``` ocaml\ntype addr = string * int\n[@@deriving yojson { optional = true }]\n```\n\nIt's also possible for many plugins to derive a function directly from a type, without declaring it first.\n\n``` ocaml\nopen OUnit2\nlet test_list_sort ctxt =\n  let sort = List.sort [%derive.ord: int * int] in\n  assert_equal ~printer:[%derive.show: (int * int) list]\n               [(1,1);(2,0);(3,5)] (sort [(2,0);(3,5);(1,1)])\n```\n\nThe `[%derive.x:]` syntax can be shortened to `[%x:]`, given that the deriver `x` exists and the payload is a type. If these conditions are not satisfied, the extension node will be left uninterpreted to minimize potential conflicts with other rewriters.\n\n### Working with existing types\n\nAt first, it may look like _deriving_ requires complete control of the type declaration. However, a lesser-known OCaml feature allows to derive functions for any existing type. Using `Stdlib.fpclass` as an example, _show_ can be derived as follows:\n\n``` ocaml\n# module M = struct\n  type myfpclass = fpclass = FP_normal | FP_subnormal | FP_zero | FP_infinite | FP_nan\n  [@@deriving show]\nend;;\nmodule M :\n  sig\n    type myfpclass =\n      fpclass =\n        FP_normal\n      | FP_subnormal\n      | FP_zero\n      | FP_infinite\n      | FP_nan\n    val pp_myfpclass : Format.formatter -\u003e fpclass -\u003e unit\n    val show_myfpclass : fpclass -\u003e string\n  end\n# M.show_myfpclass FP_normal;;\n- : string = \"FP_normal\"\n```\n\nThe module is used to demonstrate that `show_myfpclass` really accepts `Stdlib.fpclass`, and not just `M.myfpclass`.\n\nTo avoid the need to repeat the type definition, it is possible to use [ppx_import](https://github.com/ocaml-ppx/ppx_import#usage) to automatically pull in the type definition. Attributes can be attached using its `[@with]` replacement feature.\n\nPlugin conventions\n------------------\n\nIt is expected that all _deriving_ plugins will follow the same conventions, thus simplifying usage.\n\n  * By default, the functions generated by a plugin for a `type foo` are called `fn_foo` or `foo_fn`. However, if the type is called `type t`, the function will be named `foo`. The defaults can be overridden by an `affix = true|false` plugin option.\n\n  * There may be additional attributes attached to the AST. In case of a plugin named `eq` and attributes named `compare` and `skip`, the plugin must recognize all of `compare`, `skip`, `eq.compare`, `eq.skip`, `deriving.eq.compare` and `deriving.eq.skip` annotations. However, if it detects that at least one namespaced (e.g. `eq.compare` or `deriving.eq.compare`) attribute is present, it must not look at any attributes located within a different namespace. As a result, different ppx rewriters can avoid interference even if the attribute names they use overlap.\n\n  * A typical plugin should handle tuples, records, normal and polymorphic variants; builtin types: `int`, `int32`, `int64`, `nativeint`, `float`, `bool`, `char`, `string`, `bytes`, `ref`, `list`, `array`, `option`, `lazy_t` and their `Mod.t` aliases; `Result.result` available since 4.03 or in the `result` opam package; abstract types; and `_`. For builtin types, it should have customizable, sensible default behavior. This default behavior should not be used if a type has a `[@nobuiltin]` attribute attached to it, and the type should be treated as abstract. For abstract types, it should expect to find the functions it would derive itself for that type.\n\n  * If a type is parametric, the generated functions accept an argument for every type variable before all other arguments.\n\nPlugin: show\n------------\n\n_show_ derives a function that inspects a value; that is, pretty-prints it with OCaml syntax. However, _show_ offers more insight into the structure of values than the Obj-based pretty printers (e.g. `Printexc`), and more flexibility than the toplevel printer.\n\n``` ocaml\n# type t = [ `A | `B of int ] [@@deriving show];;\ntype t = [ `A | `B of i ]\nval pp : Format.formatter -\u003e [\u003c `A | `B of i ] -\u003e unit = \u003cfun\u003e\nval show : [\u003c `A | `B of i ] -\u003e string = \u003cfun\u003e\n# show (`B 1);;\n- : string = \"`B (1)\"\n```\n\nFor an abstract type `ty`, _show_ expects to find a `pp_ty` function in the corresponding module.\n\n_show_ allows to specify custom formatters for types to override default behavior. A formatter for type `t` has a type `Format.formatter -\u003e t -\u003e unit`:\n\n``` ocaml\n# type file = {\n  name : string;\n  perm : int     [@printer fun fmt -\u003e fprintf fmt \"0o%03o\"];\n} [@@deriving show];;\n# show_file { name = \"dir\"; perm = 0o755 };;\n- : string = \"{ name = \\\"dir\\\"; perm = 0o755 }\"\n```\n\nIt is also possible to use `[@polyprinter]`. The difference is that for a type `int list`, `[@printer]` should have a signature `formatter -\u003e int list -\u003e unit`, and for `[@polyprinter]` it's `('a -\u003e formatter -\u003e unit) -\u003e formatter -\u003e 'a list -\u003e unit`.\n\n`[@opaque]` is a shorthand for `[@printer fun fmt _ -\u003e Format.pp_print_string fmt \"\u003copaque\u003e\"]`.\n\nThe function `fprintf` is locally defined in the printer.\n\nBy default all constructors are printed with prefix which is dot-separated filename and module path. For example\n``` ocaml\n# module X = struct type t = C [@@deriving show] end;;\n...\n# X.(show C);;\n- : string = \"X.C\"\n```\n\nThis code will create printers which return the string `X.C`, `X` is a module path and `C` is a constructor name. File's name is omitted in the toplevel. To skip all module paths the one needs to derive show with option `with_path` (which defaults to `true`)\n\n``` ocaml\n# module X = struct type t = C [@@deriving show { with_path = false }] end;;\n...\n# X.(show C);;\n- : string = \"C\"\n```\n\n\nPlugins: eq and ord\n-------------------\n\n_eq_ derives a function comparing values by semantic equality; structural or physical depending on context. _ord_ derives a function defining a total order for values, returning a negative value if lower, `0` if equal or a positive value if greater. They're similar to `Stdlib.(=)` and `Stdlib.compare`, but are faster, allow to customize the comparison rules, and never raise at runtime. _eq_ and _ord_ are short-circuiting.\n\n``` ocaml\n# type t = [ `A | `B of int ] [@@deriving eq, ord];;\ntype t = [ `A | `B of int ]\nval equal : [\u003e `A | `B of int ] -\u003e [\u003e `A | `B of int ] -\u003e bool = \u003cfun\u003e\nval compare : [ `A | `B of int ] -\u003e [ `A | `B of int ] -\u003e int = \u003cfun\u003e\n# equal `A `A;;\n- : bool = true\n# equal `A (`B 1);;\n- : bool = false\n# compare `A `A;;\n- : int = 0\n# compare (`B 1) (`B 2);;\n- : int = -1\n```\n\nFor variants, _ord_ uses the definition order. For builtin types, properly monomorphized `(=)` is used for _eq_, or corresponding `Mod.compare` function (e.g. `String.compare` for `string`) for _ord_. For an abstract type `ty`, _eq_ and _ord_ expect to find an `equal_ty` or `compare_ty` function in the corresponding module.\n\n_eq_ and _ord_ allow to specify custom comparison functions for types to override default behavior. A comparator for type `t` has a type `t -\u003e t -\u003e bool` for _eq_ or `t -\u003e t -\u003e int` for _ord_. If an _ord_ comparator returns a value outside -1..1 range, the behavior is unspecified.\n\n``` ocaml\n# type file = {\n  name : string [@equal fun a b -\u003e String.(lowercase a = lowercase b)];\n  perm : int    [@compare fun a b -\u003e compare b a]\n} [@@deriving eq, ord];;\ntype file = { name : bytes; perm : int; }\nval equal_file : file -\u003e file -\u003e bool = \u003cfun\u003e\nval compare_file : file -\u003e file -\u003e int = \u003cfun\u003e\n# equal_file { name = \"foo\"; perm = 0o644 } { name = \"Foo\"; perm = 0o644 };;\n- : bool = true\n# compare_file { name = \"a\"; perm = 0o755 } { name = \"a\"; perm = 0o644 };;\n- : int = -1\n```\n\nPlugin: enum\n------------\n\n_enum_ is a plugin that treats variants with argument-less constructors as enumerations with an integer value assigned to every constructor. _enum_ derives functions to convert the variants to and from integers, and minimal and maximal integer value.\n\n``` ocaml\n# type insn = Const | Push | Pop | Add [@@deriving enum];;\ntype insn = Const | Push | Pop | Add\nval insn_to_enum : insn -\u003e int = \u003cfun\u003e\nval insn_of_enum : int -\u003e insn option = \u003cfun\u003e\nval min_insn : int = 0\nval max_insn : int = 3\n# insn_to_enum Pop;;\n- : int = 2\n# insn_of_enum 3;;\n- : insn option = Some Add\n```\n\nBy default, the integer value associated is `0` for lexically first constructor, and increases by one for every next one. It is possible to set the value explicitly with `[@value 42]`; it will keep increasing from the specified value.\n\nPlugins: iter, map and fold\n---------------------------\n\n_iter_, _map_ and _fold_ are three closely related plugins that generate code for traversing polymorphic data structures in lexical order and applying a user-specified action to all values corresponding to type variables.\n\n``` ocaml\n# type 'a btree = Node of 'a btree * 'a * 'a btree | Leaf [@@deriving iter, map, fold];;\ntype 'a btree = Node of 'a btree * 'a * 'a btree | Leaf\nval iter_btree : ('a -\u003e unit) -\u003e 'a btree -\u003e unit = \u003cfun\u003e\nval map_btree : ('a -\u003e 'b) -\u003e 'a btree -\u003e 'b btree = \u003cfun\u003e\nval fold_btree : ('a -\u003e 'b -\u003e 'a) -\u003e 'a -\u003e 'b btree -\u003e 'a = \u003cfun\u003e\n# let tree = (Node (Node (Leaf, 0, Leaf), 1, Node (Leaf, 2, Leaf)));;\nval tree : int btree = Node (Node (Leaf, 0, Leaf), 1, Node (Leaf, 2, Leaf))\n# iter_btree (Printf.printf \"%d\\n\") tree;;\n0\n1\n2\n- : unit = ()\n# map_btree ((+) 1) tree;;\n- : int btree = Node (Node (Leaf, 1, Leaf), 2, Node (Leaf, 3, Leaf))\n# fold_btree (+) 0 tree;;\n- : int = 3\n```\n\nPlugin: make\n--------------\n\n_make_ is a plugin that generates record constructors. Given a record, a function is generated that accepts all fields as labelled arguments and `()`; alternatively, if one field is specified as `[@main]`, it is accepted last. The fields which have a default value (fields of types `'a option`, `'a list`, and fields with `[@default]` annotation) are mapped to optional arguments; the rest are mandatory. A field of form `xs: ('a * 'a list) [@split]` corresponds to two arguments: mandatory argument `x` and optional argument `xs` with types `'a` and `'a list` correspondingly.\n\n``` ocaml\ntype record = {\n  opt  : int option;\n  lst  : int list;\n  def  : int [@default 42];\n  args : (int * int list) [@split];\n  norm : int;\n} [@@deriving make];;\nval make_record :\n  ?opt:int -\u003e\n  ?lst:int list -\u003e\n  ?def:int -\u003e\n  arg:int -\u003e\n  ?args:int list -\u003e\n  norm:int -\u003e\n  unit -\u003e\n  record\n```\n\nTo use _make_ with a set of mutually recursive type definitions, simply attach a\nsingle `[@@deriving make]` attribute and it will derive a `make_*` function for\neach record type in the set.\n\nThe deriving runtime\n--------------------\n\n_deriving_ comes with a small runtime library, the\n`Ppx_deriving_runtime` module, whose purpose is to re-export the\nmodules and types of the standard library that code producers rely\non -- ensuring hygienic code generation.\n\nBy emitting code that references to `Ppx_deriving_runtime.Array`\nmodule instead of just `Array`, plugins ensure that they can be used\nin environments where the `Array` module is redefined with\nincompatible types.\n\nBuilding ppx drivers\n--------------------\n\nBy default, _deriving_ dynlinks every plugin, whether invoked as a part of a batch compilation or from the toplevel. If this is unsuitable for you for some reason, it is possible to precompile a ppx rewriter executable that includes several _deriving_ plugins:\n\n```\n$ ocamlfind opt -predicates ppx_driver -package ppx_deriving_foo -package ppx_deriving_bar \\\n                -package ppx_deriving.main -linkpkg -linkall -o ppx_driver\n```\n\nCurrently, the resulting ppx driver still depends on Dynlink as well as retains the ability to load more plugins.\n\nDeveloping plugins\n------------------\n\nThis section only explains the tooling and best practices. Anyone aiming to implement their own _deriving_ plugin is encouraged to explore the existing ones, e.g. [eq](src_plugins/eq/ppx_deriving_eq.cppo.ml) or [show](src_plugins/show/ppx_deriving_show.cppo.ml).\n\n### Tooling and environment\n\nA _deriving_ plugin is packaged as a Findlib library; this library should include a peculiar META file. As an example, let's take a look at a description of a _yojson_ plugin:\n\n```\nversion = \"1.0\"\ndescription = \"[@@deriving yojson]\"\nexists_if = \"ppx_deriving_yojson.cma\"\n# The following part affects batch compilation and toplevel.\n# The plugin package may require any runtime component it needs.\nrequires(-ppx_driver) = \"ppx_deriving yojson\"\nppxopt(-ppx_driver) = \"ppx_deriving,./ppx_deriving_yojson.cma\"\n# The following part affects ppx driver compilation.\nrequires(ppx_driver) = \"ppx_deriving.api\"\narchive(ppx_driver, byte) = \"ppx_deriving_yojson.cma\"\narchive(ppx_driver, native) = \"ppx_deriving_yojson.cmxa\"\n```\n\nThe module(s) provided by the package in the `ppxopt` variable must register the derivers using `Ppx_deriving.register \"foo\"` during loading. Any number of derivers may be registered; careful registration would allow a _yojson_ deriver to support all three of `[@@deriving yojson]`, `[@@deriving of_yojson]` and `[@@deriving to_yojson]`, as well as `[%derive.of_yojson:]` and `[%derive.to_yojson:]`.\n\nIt is possible to test the plugin without installing it by instructing _deriving_ to load it directly; the compiler should be invoked as `ocamlfind c -package ppx_deriving -ppxopt ppx_deriving,src/ppx_deriving_foo.cma ...`. The file extension is replaced with `.cmxs` automatically for native builds. This can be integrated with buildsystem, e.g. for ocamlbuild:\n\n``` ocaml\nlet () = dispatch (\n  function\n  | After_rules -\u003e\n    (* Assuming files tagged with deriving_foo are already tagged with\n       package(ppx_deriving) or anything that uses it, e.g. package(ppx_deriving.std). *)\n    flag [\"ocaml\"; \"compile\"; \"deriving_foo\"] \u0026\n      S[A\"-ppxopt\"; A\"ppx_deriving,src/ppx_deriving_foo.cma\"]\n  | _ -\u003e ()\n```\n\nAlternatively, you can quickly check the code generated by a ppx rewriter packaged with ocamlfind by running the toplevel as `ocaml -dsource` or `utop -dsource`, which will unparse the rewritten syntax tree into OCaml code and print it before executing.\n\n### Testing plugins\n\nThe main ppx_deriving binary can be used to output preprocessed source code in a human-readable form:\n\n```\n$ cat test.ml\ntype foo = A of int | B of float\n[@@deriving show]\n$ ocamlfind ppx_deriving/ppx_deriving \\\n    -deriving-plugin `ocamlfind query ppx_deriving`/ppx_deriving_show.cma \\\n    test.ml\n```\n``` ocaml\ntype foo =\n  | A of int\n  | B of float [@@deriving show]\nlet rec (pp_foo : Format.formatter -\u003e foo -\u003e Ppx_deriving_runtime.unit) =\n  ((let open! Ppx_deriving_runtime in\n      fun fmt  -\u003e\n        function\n        | A a0 -\u003e\n            (Format.fprintf fmt \"(@[\u003c2\u003eT.A@ \";\n             (Format.fprintf fmt \"%d\") a0;\n             Format.fprintf fmt \"@])\")\n        | B a0 -\u003e\n            (Format.fprintf fmt \"(@[\u003c2\u003eT.B@ \";\n             (Format.fprintf fmt \"%F\") a0;\n             Format.fprintf fmt \"@])\"))\n  [@ocaml.warning \"-A\"])\n\nand show_foo : foo -\u003e Ppx_deriving_runtime.string =\n  fun x  -\u003e Format.asprintf \"%a\" pp_foo x\n```\n\n### Goals of the API\n\n_deriving_ is a thin wrapper over the ppx rewriter system. Indeed, it includes very little logic; the goal of the project is 1) to provide common reusable abstractions required by most, if not all, deriving plugins, and 2) encourage the deriving plugins to cooperate and to have as consistent user interface as possible.\n\nAs such, _deriving_:\n\n  * Completely defines the syntax of `[@@deriving]` annotation and unifies the plugin discovery mechanism;\n  * Provides an unified, strict option parsing API to plugins;\n  * Provides helpers for parsing annotations to ensure that the plugins interoperate with each other and the rest of the ecosystem.\n\n### Using the API\n\nComplete API documentation is available [online](http://ocaml-ppx.github.io/ppx_deriving/ppx_deriving/Ppx_deriving).\n\n#### Hygiene\n\nA very important aspect of a syntax extension is **hygiene**. Consider a case where a _deriving_ plugin makes assumptions about the interface provided by the `List` module: it will normally work as expected, but not in case where someone shadows the `List` identifier! This happens quite often in the OCaml ecosystem, e.g. the Jane Street [Core] library encourages developers to use `open Core.Std`.\n\nAdditionally, if your _deriving_ plugin inserts user-provided expressions into the generated code, a name you are using internally may accidentally collide with a user-defined name.\n\nWith _deriving_, both of these problems are solved in three easy steps:\n\n  * Create a _quoter_:\n\n    ``` ocaml\n    let quoter = Ppx_deriving.create_quoter () in\n    ...\n    ```\n\n  * Pass the user-provided expressions, if any, through the quoter, such as\n    by using a helper function:\n\n    ```ocaml\n    let attr_custom_fn attrs =\n      Ppx_deriving.(attrs |\u003e attr ~deriver \"custom_fn\" |\u003e Arg.(get_attr ~deriver expr)\n                          |\u003e quote ~quoter)\n    ```\n\n  * Wrap the generated code:\n\n    ```ocaml\n    let expr_of_typ typ =\n      let quoter = ...\n      and expr = ... in\n      Ppx_deriving.sanitize ~quoter expr\n    ```\n\n    If the plugin does not accept user-provided expressions, `sanitize expr` could be used\n    instead.\n\n#### FAQ\n\nThe following is a list of tips for developers trying to use the ppx interface:\n\n  * Module paths overwhelm you? Open all of the following modules, they don't conflict with each other: `Longident`, `Location`, `Asttypes`, `Parsetree`, `Ast_helper`, `Ast_convenience`.\n  * Need to insert some ASTs? See [ppx_metaquot](https://github.com/alainfrisch/ppx_tools/blob/master/ppx_metaquot.ml); it is contained in the `ppx_tools.metaquot` package.\n  * Need to display an error? Use `Ppx_deriving.raise_errorf ~loc \"Cannot derive Foo: (error description)\"` ([doc](http://ocaml-ppx.github.io/ppx_deriving/ppx_deriving/Ppx_deriving/index.html#val-raise_errorf)); keep it clear which deriving plugin raised the error!\n  * Need to derive a function name from a type name? Use [Ppx_deriving.mangle_type_decl](http://ocaml-ppx.github.io/ppx_deriving/ppx_deriving/Ppx_deriving/index.html#val-mangle_type_decl) and [Ppx_deriving.mangle_lid](http://ocaml-ppx.github.io/ppx_deriving/ppx_deriving/Ppx_deriving/index.html#val-mangle_lid).\n  * Need to fetch an attribute from a node? Use `Ppx_deriving.attr ~prefix \"foo\" nod.nod_attributes` ([doc](http://ocaml-ppx.github.io/ppx_deriving/ppx_deriving/Ppx_deriving/index.html#val-attr)); this takes care of interoperability.\n  * Put all functions derived from a set of type declarations into a single `let rec` block; this reflects the always-recursive nature of type definitions.\n  * Need to handle polymorphism? Use [Ppx_deriving.poly_fun_of_type_decl](http://ocaml-ppx.github.io/ppx_deriving/ppx_deriving/Ppx_deriving/index.html#val-poly_fun_of_type_decl) for derived functions, [Ppx_deriving.poly_arrow_of_type_decl](http://ocaml-ppx.github.io/ppx_deriving/ppx_deriving/Ppx_deriving/index.html#val-poly_arrow_of_type_decl) for signatures, and [Ppx_deriving.poly_apply_of_type_decl](http://ocaml-ppx.github.io/ppx_deriving/ppx_deriving/Ppx_deriving/index.html#val-poly_apply_of_type_decl) for \"forwarding\" the arguments corresponding to type variables to another generated function.\n  * Need to display a full path to a type, e.g. for an error message? Use [Ppx_deriving.path_of_type_decl](http://ocaml-ppx.github.io/ppx_deriving/ppx_deriving/Ppx_deriving/index.html#val-path_of_type_decl).\n  * Need to apply a sequence or a binary operator to variant, tuple or record elements? Use [Ppx_deriving.fold_exprs](http://ocaml-ppx.github.io/ppx_deriving/ppx_deriving/Ppx_deriving/index.html#val-fold_exprs).\n  * Don't forget to display an error message if your plugin doesn't parse any options.\n\nLicense\n-------\n\n_deriving_ is distributed under the terms of [MIT license](LICENSE.txt).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Focaml-ppx%2Fppx_deriving","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Focaml-ppx%2Fppx_deriving","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Focaml-ppx%2Fppx_deriving/lists"}