package ppx_variants_conv

  1. Overview
  2. Docs
Generation of accessor and iteration functions for ocaml variant types

Install

Dune Dependency

Authors

Maintainers

Sources

ppx_variants_conv-v0.15.0.tar.gz
sha256=6e7096f6e7b6c2fa916e85d2b526a4574234f72185b40f7d409d08f339dfac9c

Description

Part of the Jane Street's PPX rewriters collection.

Published: 21 Mar 2022

README

ppx_variants_conv

Generation of accessor and iteration functions for ocaml variant types.

ppx_variants_conv is a ppx rewriter that can be used to define first class values representing variant constructors, some helper functions to identify or match on individual constructors, and additional routines to fold, iterate and map over all constructors of a variant type.

It provides corresponding functionality for variant types as ppx_fields_conv provides for record types.

Basic use of [@@deriving variants] and variantslib

This code:

type 'a t =
  | A of 'a
  | B of char
  | C
  | D of int * int
  [@@deriving variants]

generates the following values:

(** first-class constructor functions *)
val a : 'a -> 'a t
val b : char -> 'a t
val c : 'a t
val d : int -> int -> 'a t

val is_a : _ t -> bool
val is_b : _ t -> bool
val is_c : _ t -> bool
val is_d : _ t -> bool

val a_val : 'a t -> 'a option
val b_val : _ t -> char option
val c_val : _ t -> unit option
val d_val : _ t -> (int * int) option

(** higher order variants and functions over all variants *)
module Variants : sig
  val a : ('a -> 'a t)         Variant.t
  val b : (char -> 'a t)       Variant.t
  val c : ('a t)               Variant.t
  val d : (int -> int -> 'a t) Variant.t

  val fold :
    init: 'b
    -> a:('b -> ('a -> 'a t)         Variant.t -> 'c)
    -> b:('c -> (char -> 'a t)       Variant.t -> 'd)
    -> c:('d -> ('a t)               Variant.t -> 'e)
    -> d:('e -> (int -> int -> 'a t) Variant.t -> 'f)
    -> 'f

  val iter :
       a: (('a -> 'a t)         Variant.t -> unit)
    -> b: ((char -> 'a t)       Variant.t -> unit)
    -> c: (('a t)               Variant.t -> unit)
    -> d: ((int -> int -> 'a t) Variant.t -> unit)
    -> unit

  val map :
    'a t
    -> a: (('a -> 'a t)         Variant.t -> 'a                 -> 'r)
    -> b: ((char -> 'a t)       Variant.t -> char               -> 'r)
    -> c: (('a t)               Variant.t                       -> 'r)
    -> d: ((int -> int -> 'a t) Variant.t -> int -> int -> 'a t -> 'r)
    -> 'r

  val make_matcher :
       a:(('a -> 'a t)         Variant.t -> 'b -> ('c -> 'd)         * 'e)
    -> b:((char -> 'f t)       Variant.t -> 'e -> (char -> 'd)       * 'g)
    -> c:('h t                 Variant.t -> 'g -> (unit -> 'd)       * 'i)
    -> d:((int -> int -> 'j t) Variant.t -> 'i -> (int -> int -> 'd) * 'k)
    -> 'b
    -> ('c t -> 'd) * 'k

  val to_rank : _ t -> int
  val to_name : _ t -> string

  (** name * number of arguments, ie [("A", 1); ("B", 1); ("C", 0); ("D", 2)]. *)
  val descriptions : (string * int) list
end

Variant.t is defined in Variantslib as follows:

module Variant = struct
  type 'constructor t = {
    name : string;
    (* the position of the constructor in the type definition, starting from 0 *)
    rank : int;
    constructor : 'constructor
  }
end

The fold, iter, and map functions are useful in dealing with the totality of variants. For example, to get a list of all variants when all the constructors are nullary:

type t =
  | First
  | Second
  | Third
  [@@deriving variants]
let all =
  let add acc var = var.Variantslib.Variant.constructor :: acc in
  Variants.fold ~init:[]
    ~first:add
    ~second:add
    ~third:add

Just like with [@@deriving fields], if the type changes, the compiler will complain until this definition is updated as well.

ppx_variant_libs works similarly on simple polymorphic variants (without row variables and without inclusion).

Dependencies (5)

  1. ppxlib >= "0.23.0"
  2. dune >= "2.0.0"
  3. variantslib >= "v0.15" & < "v0.16"
  4. base >= "v0.15" & < "v0.16"
  5. ocaml >= "4.08.0"

Dev Dependencies

None

Used by (6)

  1. bin_prot = "v0.15.0"
  2. cookies
  3. nacc
  4. pkcs11 >= "0.17.1"
  5. ppx_bap < "v0.14.0"
  6. ppx_jane = "v0.15.0"

Conflicts

None