File: README.md

package info (click to toggle)
enumerate 111.08.00-3
  • links: PTS, VCS
  • area: main
  • in suites: buster
  • size: 308 kB
  • ctags: 389
  • sloc: ml: 6,066; makefile: 55
file content (110 lines) | stat: -rw-r--r-- 2,854 bytes parent folder | download | duplicates (3)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
This library defines a syntax extension allowing you to automatically
produce a list of all values of a type (for a type which only has
finitely many values).

Basic Usage
===========

The basic usage is simply to add "with enumerate" after the type
definition.  For example:

    type t =
    | Foo
    | Bar of bool
    | Baz of [`A | `B of unit option]
    with 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 'with enumerate' on polymorphic
types produces a function for [all].  For example,

    type 'a t =
    | Foo
    | Bar of 'a option
    with 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]
      } with 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 with 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
`with enumerate`:

    type t =
    | Foo
    | Bar of Small_int.t option
    with 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 lead
to duplicate values in the resulting lists:

    type t = [ `A ] with enumerate
    let () = assert (<:all< [ t | t ] >> = [ `A; `A ])