package ppx_enumerate

  1. Overview
  2. Docs
Generate a list containing all values of a finite type

Install

Dune Dependency

Authors

Maintainers

Sources

ppx_enumerate-v0.10.0.tar.gz
md5=934dd368ce0a45366c0f47a9acfa2e61

Description

Part of the Jane Street's PPX rewriters collection.

Published: 15 Dec 2017

README

ppx_enumerate

Generate a list containing all values of a finite type.

ppx_enumerate is a ppx rewriter which generates a definition for the list of all values of a type with (for a type which only has finitely many values).

Basic Usage

The basic usage is simply to add "[@@deriving enumerate]" after the type definition. For example:

type t =
  | Foo
  | Bar of bool
  | Baz of [`A | `B of unit option]
  [@@deriving enumerate]

will produce a value val all : t list, whose value is equal to

[ Foo; Bar true; Bar false; Baz `A; Baz (`B None); Baz (`B Some ()) ]

in some order (that is, there is no guarantee about the order of the list).

Polymorphic types

In a similar fashion as sexplib, using '[@@deriving enumerate]' on polymorphic types produces a function for [all]. For example,

type 'a t =
  | Foo
  | Bar of 'a option
  [@@deriving enumerate]

will produce a value val all : 'a list -> 'a t list, whose value is semantically equal to

fun all_of_a -> Foo :: Bar None :: List.map all_of_a ~f:(fun x -> Bar (Some x))

Types not named t

If the type is not named t, then the enumeration is called all_of_<type_name> instead of all.

Records and Tuples

Product types are supported as well as sum types. For example,

type t =
  { foo : [`A | `B]
  ; bar : [`C | `D]
  } [@@deriving enumerate]

produces a val all : t list whose value is equal (up to order) to:

[ { foo = `A; bar = `C }; { foo = `A; bar = `D };
  { foo = `B; bar = `C }; { foo = `B; bar = `D };
]

Tuples and variants with multiple arguments are similarly supported.

Overriding the all value

Just like with sexplib, it can sometimes be useful to provide a custom value of all. For example, you might define a type of bounded integers:

module Small_int : sig
  type t = private int [@@deriving enumerate]
  val create_exn : int -> t
end = struct
  type t = int
  let limit = 100
  let create_exn i = if i < 0 || i >= limit then failwith "out of bounds"; i
  let all = List.init limit ~f:(fun i -> i)
end

You could then use Small_int.t as normal with other types using [@@deriving enumerate]:

type t =
  | Foo
  | Bar of Small_int.t option
  [@@deriving enumerate]

Using all without defining a type name

You don't have to define a type name to be able to create the list of values of a type. You do it for any type expression by using the all quotation. For example:

[%all: bool * bool]

which will evaluate to:

[ (true, true); (true, false); (false, false); (false, true) ]

Known issues

Using all for polymorphic variants with duplicated constructors leads to duplicate values in the resulting lists:

type t = [ `A ] [@@deriving enumerate]
let () = assert ([%all: [ t | t ] ] = [ `A; `A ])

Dependencies (7)

  1. ocaml-migrate-parsetree >= "0.4" & < "2.0.0"
  2. jbuilder >= "1.0+beta12"
  3. ppx_type_conv >= "v0.10" & < "v0.11"
  4. ppx_metaquot >= "v0.10" & < "v0.11"
  5. ppx_driver >= "v0.10" & < "v0.11"
  6. ppx_core >= "v0.10" & < "v0.11"
  7. ocaml >= "4.04.1"

Dev Dependencies

None

Used by (3)

  1. frenetic >= "5.0.0" & < "5.0.5"
  2. ppx_bap < "v0.14.0"
  3. ppx_base = "v0.10.0"

Conflicts

None