# `StreamData`
[🔗](https://github.com/whatyouhide/stream_data/blob/v1.4.0/lib/stream_data.ex#L1)

Functions to create and combine generators.

A generator is a `StreamData` struct. Generators can be created through the
functions exposed in this module, like `constant/1`, and by combining other
generators through functions like `bind/2`.

Similar to the `Stream` module, the functions in this module return a lazy
construct. We can get values out of a generator by enumerating the generator.
Generators always generate an infinite stream of values (which are randomized
most of the time).

For example, to get an infinite stream of integers that starts with small
integers and progressively grows the boundaries, you can use `integer/0`:

    Enum.take(StreamData.integer(), 10)
    #=> [-1, 0, -3, 4, -4, 5, -1, -3, 5, 8]

As you can see above, values emitted by a generator are not unique.

In many applications of generators, the longer the generator runs the larger
the generated values will be. For integers, a larger integer means a bigger number.
For lists, it may mean a list with more elements. This is controlled by a parameter
that we call the **generation size** (see the "Generation size" section below).

StreamData is often used to generate random values. It is also the foundation
for property-based testing. See `ExUnitProperties` for more information.

## Enumeration

Generators implement the `Enumerable` protocol. The enumeration starts with a
small generation size, which increases when the enumeration continues (up to a
fixed maximum size).

Since generators are proper streams, functions from the `Stream` module can be
used to stream values out of them. For example, to build an infinite stream of
positive even integers, you can do:

    StreamData.integer()
    |> Stream.filter(& &1 > 0)
    |> Stream.map(& &1 * 2)
    |> Enum.take(10)
    #=> [4, 6, 4, 10, 14, 16, 4, 16, 36, 16]

Generators that are manipulated via the `Stream` and `Enum` modules are no
longer **shrinkable** (see the section about shrinking below). If you want
generation through the `Enumerable` protocol to be reproducible, see `seeded/2`.

## Generation size

Generators have access to a generation parameter called the **generation
size**, which is a non-negative integer. This parameter is meant to bind the
data generated by each generator in a way that is completely up to the
generator. For example, a generator that generates integer can use the `size`
parameter to generate integers inside the `-size..size` range. In a similar
way, a generator that generates lists could use this parameter to generate a
list with `0` to `size` elements. During composition, it is common for the
"parent generator" to pass the size to the composed generators.

When creating generators, they can access the generation size using the
`sized/1` function. Generators can be resized to a fixed generation size using
`resize/2`.

## Shrinking

`StreamData` generators are also shrinkable. The idea behind shrinking is
to find the simplest value that respects a certain condition. For example,
during property-based tests, we use shrinking to find the integer closest to 0
or the smallest list that makes a test fail. By reporting the simplest data
structure that triggers an error, the failure becomes easier to understand
and reproduce.

Each generator has its own logic to shrink values. Those are outlined in each
generator documentation.

Note that the generation size is not related in any way to shrinking: while
intuitively one may think that shrinking just means decreasing the generation
size, in reality the shrinking rule is bound to each generated value. One way
to look at it is that shrinking a list is always the same, regardless of its
generated length.

## Special generators

Some Elixir types are implicitly converted to `StreamData` generators when
composed or used in property-based testing. These types are:

  * atoms - they generate themselves. For example, `:foo` is equivalent to
    `StreamData.constant(:foo)`.

  * tuples of generators - they generate tuples where each value is a value
    generated by the corresponding generator, exactly like described in
    `tuple/1`. For example, `{StreamData.integer(), StreamData.boolean()}`
    generates entries like `{10, false}`.

Note that *these terms must be explicitly converted to StreamData generators*.
This means that these terms are not full-fledged generators. For example, atoms
cannot be enumerated directly as they don't implement the `Enumerable` protocol.
However, `StreamData.constant(:foo)` is enumerable as it has been wrapped in
a `StreamData` function.

# `t`

```elixir
@opaque t(a)
```

An opaque type that represents a `StreamData` generator that generates values
of type `a`.

# `atom`

```elixir
@spec atom(:alphanumeric | :alias) :: t(atom())
```

Generates atoms of various `kind`s.

`kind` can be:

  * `:alphanumeric` - this generates alphanumeric atoms that don't need to be quoted when
    written as literals. For example, it will generate `:foo` but not `:"foo bar"`.

  * `:alias` - generates Elixir aliases like `Foo` or `Foo.Bar.Baz`.

These are some of the most common kinds of atoms usually used in Elixir applications. If you
need completely arbitrary atoms, you can use a combination of `map/2`, `String.to_atom/1`,
and string-focused generators to transform arbitrary strings into atoms:

    printable_atom =
      StreamData.map(
        StreamData.string(:printable, max_length: 255),
        &String.to_atom/1
      )

Bear in mind the [system limit](http://erlang.org/doc/efficiency_guide/advanced.html#system-limits)
of 255 characters in an atom when doing so.

## Examples

    Enum.take(StreamData.atom(:alphanumeric), 3)
    #=> [:xF, :y, :B_]

## Shrinking

Shrinks towards smaller atoms and towards "simpler" letters (like towards only alphabet
letters).

# `binary`

```elixir
@spec binary(keyword()) :: t(binary())
```

Generates binaries.

The length of the generated binaries is limited by the generation size.

## Options

  * `:length` - (non-negative integer) sets the exact length of the generated
    binaries (same as in `list_of/2`).

  * `:min_length` - (non-negative integer) sets the minimum length of the
    generated binaries (same as in `list_of/2`). Ignored if `:length` is
    present.

  * `:max_length` - (non-negative integer) sets the maximum length of the
    generated binaries (same as in `list_of/2`). Ignored if `:length` is
    present.

## Examples

    Enum.take(StreamData.binary(), 3)
    #=> [<<1>>, "", "@Q"]

## Shrinking

Values generated by this generator shrink by becoming smaller binaries and by
having individual bytes that shrink towards `0`.

# `bind`

```elixir
@spec bind(t(a), (a -&gt; t(b))) :: t(b) when a: term(), b: term()
```

Binds each element generated by `data` to a new generator returned by applying `fun`.

This function is the basic mechanism for composing generators. It takes a
generator `data` and invokes `fun` with each element in `data`. `fun` must
return a new *generator* that is effectively used to generate items from
now on.

## Examples

Say we wanted to create a generator that returns two-element tuples where the
first element is a non-empty list, and the second element is a random element from that
list. To do that, we can first generate a list and then bind a function to
that list; this function will return the list and a random element from it.

    StreamData.bind(StreamData.list_of(StreamData.integer(), min_length: 1), fn list ->
      StreamData.bind(StreamData.member_of(list), fn elem ->
        StreamData.constant({list, elem})
      end)
    end)

## Shrinking

The generator returned by `bind/2` shrinks by first shrinking the outer
generator given as `data` and then by shrinking the value generated by the
inner generator. When `data` shrinks, `fun` is once more applied on the
shrunk value and returns a whole new generator, which will most likely
emit new items.

# `bind_filter`

```elixir
@spec bind_filter(
  t(a),
  (a -&gt; {:cont, t(b)} | :skip)
  | (a, non_neg_integer() -&gt; {:cont, t(b)} | :skip),
  non_neg_integer()
) :: t(b)
when a: term(), b: term()
```

Binds each element generated by `data` and to a new generator returned by
applying `fun` or filters the generated element.

Works similarly to `bind/2` but allows to filter out unwanted values. It takes
a generator `data` and invokes `fun` with each element generated by `data`.
`fun` must return one of:

  * `{:cont, generator}` - `generator` is then used to generate the next
    element

  * `:skip` - the value generated by `data` is filtered out and a new element
    is generated

Since this function acts as a filter as well, it behaves similarly to
`filter/3`: when more than `max_consecutive_failures` elements are filtered
out (that is, `fun` returns `:skip`), a `StreamData.FilterTooNarrowError` is
raised. See the documentation for `filter/3` for suggestions on how to avoid
such errors.

The function can accept one or two arguments. If a two-argument function is
passed, the second argument will be the number of tries left before raising
`StreamData.FilterTooNarrowError`.

## Examples

Say we wanted to create a generator that generates two-element tuples where
the first element is a list of integers with an even number of members and the
second element is a member of that list. We can do that by generating a list
and, if it has even length, taking an element out of it, otherwise filtering
it out.

    require Integer

    list_data = StreamData.list_of(StreamData.integer(), min_length: 1)

    data =
      StreamData.bind_filter(list_data, fn
        list when Integer.is_even(length(list)) ->
          inner_data = StreamData.bind(StreamData.member_of(list), fn member ->
            StreamData.constant({list, member})
          end)
          {:cont, inner_data}
        _odd_list ->
          :skip
      end)

    Enum.at(data, 0)
    #=> {[-6, -7, -4, 5, -9, 8, 7, -9], 5}

## Shrinking

This generator shrinks like `bind/2` but values that are skipped are not used
for shrinking (similarly to how `filter/3` works).

# `bitstring`

```elixir
@spec bitstring(keyword()) :: t(bitstring())
```

Generates bitstrings.

The length of the generated bitstring is limited by the generation size.

## Options

  * `:length` - (non-negative integer) sets the exact length of the generated
    bitstrings (same as in `list_of/2`).

  * `:min_length` - (non-negative integer) sets the minimum length of the
    generated bitstrings (same as in `list_of/2`). Ignored if `:length` is
    present.

  * `:max_length` - (non-negative integer) sets the maximum length of the
    generated bitstrings (same as in `list_of/2`). Ignored if `:length` is
    present.

## Examples

    Enum.take(StreamData.bitstring(), 3)
    #=> [<<0::size(1)>>, <<2::size(2)>>, <<5::size(3)>>]

## Shrinking

Values generated by this generator shrink by becoming smaller bitstrings and
by having the individual bits go towards `0`.

# `boolean`

```elixir
@spec boolean() :: t(boolean())
```

Generates boolean values.

## Examples

    Enum.take(StreamData.boolean(), 3)
    #=> [true, true, false]

## Shrinking

Shrinks towards `false`.

# `byte`

```elixir
@spec byte() :: t(byte())
```

Generates bytes.

A byte is an integer between `0` and `255`.

## Examples

    Enum.take(StreamData.byte(), 3)
    #=> [102, 161, 13]

## Shrinking

Values generated by this generator shrink like integers, so towards bytes
closer to `0`.

# `chardata`
*since 0.6.0* 

```elixir
@spec chardata() :: t(IO.chardata())
```

Generates chardata.

Chardata are values of the `t:IO.chardata/0` type.

## Examples

    Enum.take(StreamData.chardata(), 3)
    #=> ["", [""], [12174]]

## Shrinking

Shrinks towards less nested chardata and ultimately towards smaller binaries.

# `check_all`

```elixir
@spec check_all(t(a), Keyword.t(), (a -&gt; {:ok, term()} | {:error, b})) ::
  {:ok, map()} | {:error, map()}
when a: term(), b: term()
```

Checks the behaviour of a given function on values generated by `data`.

This function takes a generator and a function `fun` and verifies that that
function "holds" for all generated data. `fun` is called with each generated
value and can return one of:

  * `{:ok, term}` - means that the function "holds" for the given value. `term`
    can be anything and will be used for internal purposes by `StreamData`.

  * `{:error, term}` - means that the function doesn't hold for the given
    value. `term` is the term that will be shrunk to find the minimal value
    for which `fun` doesn't hold. See below for more information on shrinking.

When a value is found for which `fun` doesn't hold (returns `{:error, term}`),
`check_all/3` tries to shrink that value in order to find a minimal value that
still doesn't satisfy `fun`.

The return value of this function is one of:

  * `{:ok, ok_map}` - if all generated values satisfy `fun`. `ok_map` is a map
    of metadata that contains no keys for now.

  * `{:error, error_map}` - if a generated value doesn't satisfy `fun`.
    `error_map` is a map of metadata that contains the following keys:

    * `:original_failure` - if `fun` returned `{:error, term}` for a generated
      value, this key in the map will be `term`.

    * `:shrunk_failure` - the value returned in `{:error, term}` by `fun`
      when invoked with the smallest failing value that was generated.

    * `:nodes_visited` - the number of nodes (a positive integer) visited in
      the shrinking tree in order to find the smallest value. See also the
      `:max_shrinking_steps` option.

    * `:successful_runs` - the number of successful runs before a failing value was found.

## Options

This function takes the following options:

  * `:initial_seed` - three-element tuple with three integers that is used as
    the initial random seed that drives the random generation. This option is
    required.

  * `:initial_size` - (non-negative integer) the initial generation size used
    to start generating values. The generation size is then incremented by `1`
    on each iteration. See the "Generation size" section of the module
    documentation for more information on generation size. Defaults to `1`.

  * `:max_runs` - (non-negative integer) the total number of elements to
    generate out of `data` and check through `fun`. Defaults to `100`.

  * `:max_run_time` - (non-negative integer) the total number of time (in milliseconds)
    to run a given check for. This is not used by default, so unless a value
    is given, then the length of the check will be determined by `:max_runs`.
    If both `:max_runs` and `:max_run_time` are given, then the check will finish at
    whichever comes first, `:max_runs` or `:max_run_time`.

  * `:max_shrinking_steps` - (non-negative integer) the maximum numbers of
    shrinking steps to perform in case `check_all/3` finds an element that
    doesn't satisfy `fun`. Defaults to `100`.

## Examples

Let's try out a contrived example: we want to verify that the `integer/0`
generator generates integers that are not `0` or multiples of `11`. This
verification is broken by design because `integer/0` is likely to generate
multiples of `11` at some point, but it will show the capabilities of
`check_all/3`. For the sake of the example, let's say we want the values that
fail to be represented as strings instead of the original integers that
failed. We can implement what we described like this:

    options = [initial_seed: :os.timestamp()]

    {:error, metadata} = StreamData.check_all(StreamData.integer(), options, fn int ->
      if int == 0 or rem(int, 11) != 0 do
        {:ok, nil}
      else
        {:error, Integer.to_string(int)}
      end
    end)

    metadata.nodes_visited
    #=> 7
    metadata.original_failure
    #=> 22
    metadata.shrunk_failure
    #=> 11

As we can see, the function we passed to `check_all/3` "failed" for `int =
22`, and `check_all/3` was able to shrink this value to the smallest failing
value, which in this case is `11`.

# `codepoint`
*since 0.6.0* 

```elixir
@spec codepoint(:ascii | :alphanumeric | :printable | :utf8) :: t(char())
```

Generates an integer corresponding to a valid UTF-8 codepoint of the given kind.

`kind` can be:

  * `:ascii` - only ASCII characters are generated. Shrinks towards lower codepoints.

  * `:alphanumeric` - only alphanumeric characters (`?a..?z`, `?A..?Z`, `?0..?9`)
  are generated. Shrinks towards `?a` following the order shown previously.

  * `:printable` - only printable codepoints
  (`String.printable?(<<codepoint::utf8>>)` returns `true`)
    are generated. Shrinks towards lower codepoints.

  * `:utf8` - all valid codepoints (`<<codepoint::utf8>>)` does not raise)
    are generated. Shrinks towards lower codepoints.

Defaults to `:utf8`.

## Examples

    Enum.take(StreamData.codepoint(), 3)
    #=> [889941, 349615, 1060099]

    Enum.take(StreamData.codepoint(:ascii), 3)
    #=> ~c"Kk:"

# `constant`

```elixir
@spec constant(a) :: t(a) when a: var
```

A generator that always generates the given term.

## Examples

    iex> Enum.take(StreamData.constant(:some_term), 3)
    [:some_term, :some_term, :some_term]

## Shrinking

This generator doesn't shrink.

# `date`
*since 1.3.0* 

```elixir
@spec date(Date.Range.t() | [option]) :: t(Date.t())
when option: {:origin, Date.t()} | {:min, Date.t()} | {:max, Date.t()}
```

Generates dates according to the given `options` or `date_range`.

## Options

  * `:origin` - (`t:Date.t/0`) if present, generated values will shrink towards this date.
    Cannot be combined with `:min` or `:max`.

  * `:min` - (`t:Date.t/0`) if present, only dates *after* this date will be
    generated. Values will shrink towards this date.

  * `:max` - (`t:Date.t/0`) if present, only dates *before* this date will be
    generated. Values will shrink towards this date.

If both `:min` and `:max` are provided, dates between the two mentioned dates will be generated.
Values will shrink towards `:min`.

If no options are provided, `:origin` will default to the current date (that is,
`Date.utc_today/0`).

## `t:Date.Range.t/0`

Alternatively a `t:Date.Range.t/0` can be given. This will generate dates in the given range,
and with the supplied `date_range.step`.

Values will shrink towards `date_range.first`.

## Calendar Support

This generator works with `m:Calendar.ISO` and any other calendar
which implements the callbacks
`c:Calendar.naive_datetime_to_iso_days/7` and `c:Calendar.naive_datetime_from_iso_days/2`.

## Examples

    Enum.take(StreamData.date(), 3)
    #=> [~D[2023-11-24], ~D[2023-11-25], ~D[2023-11-23]]

    Enum.take(StreamData.date(origin: ~D[2025-09-01]), 3)
    #=> [~D[2025-08-31], ~D[2025-08-31], ~D[2025-09-04]]

    Enum.take(StreamData.date(min: ~D[2025-01-01], max: ~D[2025-01-31]), 3)
    #=> [~D[2025-01-27], ~D[2025-01-21], ~D[2025-01-16]]

    Enum.take(StreamData.date(Date.range(~D[2025-01-01], ~D[2025-01-31])), 3)
    #=> [~D[2025-01-29], ~D[2025-01-03], ~D[2025-01-15]]

# `filter`

```elixir
@spec filter(t(a), (a -&gt; as_boolean(term())), non_neg_integer()) :: t(a)
when a: term()
```

Filters the given generator `data` according to the given `predicate` function.

Only elements generated by `data` that pass the filter are kept in the
resulting generator.

If the filter is too strict, it can happen that too few values generated by `data` satisfy it.
In case more than `max_consecutive_failures` consecutive values don't satisfy the filter, a
`StreamData.FilterTooNarrowError` will be raised. There are a few ways you can avoid risking
`StreamData.FilterTooNarrowError` errors.

  * Try to make sure that your filter filters out only a small subset of the elements generated
    by `data`. For example, having something like `StreamData.filter(StreamData.integer(), &(&1 !=
    0))` is usually fine because only a very tiny part of the generation space (integers) is
    being filtered out.

  * Keep an eye on how the generation size affects the generator being filtered. For example,
    take something like `StreamData.filter(StreamData.positive_integer(), &(&1 not in 1..5)`.
    While it seems like this filter is not that strict (as we're filtering out only a handful of
    numbers out of all natural numbers), this filter will fail with small generation sizes.
    Since `positive_integer/0` returns an integer between `0..size`, if `size` is small (for
    example, less than 10) then the probability of generating many consecutive values in `1..5`
    is high.

  * Try to restructure your generator so that instead of generating many values and taking out
    the ones you don't want, you instead generate values and turn all of them into values that
    are suitable. A good example is a generator for even integers. You could write it as

        def even_integers() do
          StreamData.filter(StreamData.integer(), &Integer.is_even/1)
        end

    but this would generate many unused values, increasing likeliness of
    `StreamData.FilterTooNarrowError` errors and performing inefficiently. Instead, you can use
    `map/2` to turn all integers into even integers:

        def even_integers() do
          StreamData.map(StreamData.integer(), &(&1 * 2))
        end

## Shrinking

All the values that each generated value shrinks to satisfy `predicate` as
well.

# `fixed_list`

```elixir
@spec fixed_list([t(a)]) :: t([a]) when a: term()
```

Generates a list of fixed length where each element is generated from the
corresponding generator in `data`.

## Examples

    data = StreamData.fixed_list([StreamData.integer(), StreamData.binary()])
    Enum.take(data, 3)
    #=> [[1, <<164>>], [2, ".T"], [1, ""]]

## Shrinking

Shrinks by shrinking each element in the generated list according to the
corresponding generator. Shrunk lists never lose elements.

# `fixed_map`

```elixir
@spec fixed_map(map() | keyword()) :: t(map())
```

Generates maps with fixed keys and generated values.

`data_map` is a map or keyword list of `fixed_key => data` pairs. Maps generated by this
generator will have the same keys as `data_map` and values corresponding to values generated by
the generator under those keys.

See also `optional_map/1`.

## Examples

    data = StreamData.fixed_map(%{
      integer: StreamData.integer(),
      binary: StreamData.binary(),
    })
    Enum.take(data, 3)
    #=> [%{binary: "", integer: 1}, %{binary: "", integer: -2}, %{binary: "R1^", integer: -3}]

## Shrinking

This generator shrinks by shrinking the values of the generated map.

# `float`

```elixir
@spec float(keyword()) :: t(float())
```

Generates floats according to the given `options`.

The complexity of the generated floats grows proportionally to the generation size.

## Options

  * `:min` - (float) if present, the generated floats will be greater than or equal to this
    value.

  * `:max` - (float) if present, the generated floats will be less than or equal to this value.

If neither of `:min` or `:max` is provided, then unbounded floats will be generated.

## Shrinking

Values generated by this generator will shrink towards simpler floats. Such values are not
guaranteed to shrink towards smaller or larger values (but they will never violate the `:min` or
`:max` options).

# `frequency`

```elixir
@spec frequency([{pos_integer(), t(a)}]) :: t(a) when a: term()
```

Generates values from different generators with specified probability.

`frequencies` is a list of `{frequency, data}` where `frequency` is an integer
and `data` is a generator. The resulting generator will generate data from one
of the generators in `frequency`, with probability `frequency / vsum_of_frequencies`.

## Examples

Let's build a generator that returns a binary around 25% of the time and an
integer around 75% of the time. We'll use `integer/0` first so that generated values
will shrink towards integers.

    ints_and_some_bins = StreamData.frequency([
      {3, StreamData.integer()},
      {1, StreamData.binary()},
    ])
    Enum.take(ints_and_some_bins, 3)
    #=> ["", -2, -1]

## Shrinking

This generator first shrinks towards values generated by generators earlier
in the list of `frequencies`, and then shrinks the generated value itself.

# `integer`

```elixir
@spec integer() :: t(integer())
```

Generates integers bound by the generation size.

## Examples

    Enum.take(StreamData.integer(), 3)
    #=> [1, -1, -3]

## Shrinking

Generated values shrink towards `0`.

# `integer`

```elixir
@spec integer(Range.t()) :: t(integer())
```

Generates an integer in the given `range`.

The generation size is ignored since the integer always lies inside `range`.

## Examples

    Enum.take(StreamData.integer(4..8), 3)
    #=> [6, 7, 7]

## Shrinking

Shrinks towards the smallest absolute value that still lie in `range`.

# `iodata`

```elixir
@spec iodata() :: t(iodata())
```

Generates iodata.

Iodata are values of the `t:iodata/0` type.

## Examples

    Enum.take(StreamData.iodata(), 3)
    #=> [[""], <<198>>, [115, 172]]

## Shrinking

Shrinks towards less nested iodata and ultimately towards smaller binaries.

# `iolist`

```elixir
@spec iolist() :: t(iolist())
```

Generates iolists.

Iolists are values of the `t:iolist/0` type.

## Examples

    Enum.take(StreamData.iolist(), 3)
    #=> [[164 | ""], [225], ["" | ""]]

## Shrinking

Shrinks towards smaller and less nested lists and towards bytes instead of
binaries.

# `keyword_of`

```elixir
@spec keyword_of(t(a)) :: t(keyword(a)) when a: term()
```

Generates keyword lists where values are generated by `value_data`.

Keys are always atoms.

## Examples

    Enum.take(StreamData.keyword_of(StreamData.integer()), 3)
    #=> [[], [sY: 1], [t: -1]]

## Shrinking

This generator shrinks equivalently to a list of key-value tuples generated by
`list_of/1`, that is, by shrinking the values in each tuple and also reducing
the size of the generated keyword list.

# `list_of`

```elixir
@spec list_of(t(a)) :: t([a]) when a: term()
```

Generates lists where each values is generated by the given `data`.

The same as calling `list_of/2` with `[]` as options.

# `list_of`

```elixir
@spec list_of(
  t(a),
  keyword()
) :: t([a])
when a: term()
```

Generates lists where each values is generated by the given `data`.

Each generated list can contain duplicate elements. The length of the
generated list is bound by the generation size. If the generation size is `0`,
the empty list will always be generated. Note that the accepted options
provide finer control over the size of the generated list. See the "Options"
section below.

## Options

  * `:length` - (integer or range) if an integer, the exact length the
    generated lists should be; if a range, the range in which the length of
    the generated lists should be. If provided, `:min_length` and
    `:max_length` are ignored.

  * `:min_length` - (integer) the minimum length of the generated lists.

  * `:max_length` - (integer) the maximum length of the generated lists.

## Examples

    Enum.take(StreamData.list_of(StreamData.binary()), 3)
    #=> [[""], [], ["", "w"]]

    Enum.take(StreamData.list_of(StreamData.integer(), length: 3), 3)
    #=> [[0, 0, -1], [2, -1, 1], [0, 3, -3]]

    Enum.take(StreamData.list_of(StreamData.integer(), max_length: 1), 3)
    #=> [[1], [], []]

## Shrinking

This generator shrinks by taking elements out of the generated list and also
by shrinking the elements of the generated list. Shrinking still respects any
possible length-related option: for example, if `:min_length` is provided, all
shrunk list will have more than `:min_length` elements.

# `map`

```elixir
@spec map(t(a), (a -&gt; b)) :: t(b) when a: term(), b: term()
```

Maps the given function `fun` over the given generator `data`.

Returns a new generator that returns elements from `data` after applying `fun`
to them.

## Examples

    iex> data = StreamData.map(StreamData.integer(), &Integer.to_string/1)
    iex> Enum.take(data, 3)
    ["1", "0", "3"]

## Shrinking

This generator shrinks exactly like `data`, but with `fun` mapped over the
shrunk data.

# `map_of`

```elixir
@spec map_of(t(key), t(value), keyword()) :: t(%{optional(key) =&gt; value})
when key: term(), value: term()
```

Generates maps with keys from `key_data` and values from `value_data`.

Since maps require keys to be unique, this generator behaves similarly to
`uniq_list_of/2`: if more than `max_tries` duplicate keys are generated
consequently, it raises a `StreamData.TooManyDuplicatesError` exception.

## Options

  * `:length` - (non-negative integer) same as in `list_of/2`.

  * `:min_length` - (non-negative integer) same as in `list_of/2`.

  * `:max_length` - (non-negative integer) same as in `list_of/2`.

## Examples

    Enum.take(StreamData.map_of(StreamData.integer(), StreamData.boolean()), 3)
    #=> [%{}, %{1 => false}, %{-2 => true, -1 => false}]

## Shrinking

Shrinks towards smallest maps and towards shrinking keys and values according
to the respective generators.

# `mapset_of`

```elixir
@spec mapset_of(
  t(a),
  keyword()
) :: t(MapSet.t(a))
when a: term()
```

Generates sets where values are generated by `data`.

## Options

  * `:max_tries` - (non-negative integer) the maximum number of times that
    this generator tries to generate the next element of the set before
    giving up and raising a `StreamData.TooManyDuplicatesError` in case it
    can't find a unique element to generate.

## Examples

    Enum.take(StreamData.mapset_of(StreamData.integer()), 3)
    #=> [#MapSet<[-1]>, #MapSet<[1, 2]>, #MapSet<[-3, 2, 3]>]

## Shrinking

This generator shrinks in the same way as `uniq_list_of/2`, by removing
elements and shrinking elements as well.

# `maybe_improper_list_of`

```elixir
@spec maybe_improper_list_of(t(a), t(b)) :: t(maybe_improper_list(a, b))
when a: term(), b: term()
```

Generates lists of elements out of `first` with a chance of them being
improper with the improper ending taken out of `improper`.

Behaves similarly to `nonempty_improper_list_of/2` but can generate empty
lists and proper lists as well.

## Examples

    data = StreamData.maybe_improper_list_of(StreamData.byte(), StreamData.binary())
    Enum.take(data, 3)
    #=> [[60 | "."], [], [<<212>>]]

## Shrinking

Shrinks towards smaller lists and shrunk elements in those lists, and
ultimately towards proper lists.

# `member_of`

```elixir
@spec member_of(Enumerable.t()) :: t(term())
```

Generates elements taken randomly out of `enum`.

`enum` must be a non-empty and **finite** enumerable. If given an empty
enumerable, this function raises an error. If given an infinite enumerable,
this function will not terminate.

## Examples

    Enum.take(StreamData.member_of([:ok, 4, "hello"]), 3)
    #=> [4, 4, "hello"]

## Shrinking

This generator shrinks towards elements that appear earlier in `enum`.

# `non_negative_integer`
*since 0.6.0* 

```elixir
@spec non_negative_integer() :: t(non_neg_integer())
```

Generates non-negative integers bound by the generation size.

## Examples

    Enum.take(StreamData.non_negative_integer(), 3)
    #=> [0, 2, 0]

## Shrinking

Generated values shrink towards `0`.

# `nonempty`

```elixir
@spec nonempty(t(Enumerable.t())) :: t(Enumerable.t())
```

Constrains the given `enum_data` to be non-empty.

`enum_data` must be a generator that emits enumerables, such as lists
and maps. `nonempty/1` will filter out enumerables that are empty
(`Enum.empty?/1` returns `true`).

## Examples

    Enum.take(StreamData.nonempty(StreamData.list_of(StreamData.integer())), 3)
    #=> [[1], [-1, 0], [2, 1, -2]]

# `nonempty_improper_list_of`

```elixir
@spec nonempty_improper_list_of(t(a), t(b)) :: t(nonempty_improper_list(a, b))
when a: term(), b: term()
```

Generates non-empty improper lists where elements of the list are generated
out of `first` and the improper ending out of `improper`.

## Examples

    data = StreamData.nonempty_improper_list_of(StreamData.byte(), StreamData.binary())
    Enum.take(data, 3)
    #=> [[42], [56 | <<140, 137>>], [226 | "j"]]

## Shrinking

Shrinks towards smaller lists (that are still non-empty, having the improper
ending) and towards shrunk elements of the list and a shrunk improper
ending.

# `nullable`

```elixir
@spec nullable(
  t(a),
  keyword()
) :: t(nil | a)
when a: term()
```

Generates either `nil` or the value generated by the given `data`.

The frequency distribution can be specified using the `ratio` option.

## Options

  * `:ratio` - (float in between `0.0` and `1.0`, not included) specifies the
    frequency with which `nil` should be selected. Higher means that `nil` is
    more likely to be selected. Defaults to `0.5`.

## Examples

    Enum.take(StreamData.nullable(StreamData.integer()), 10)
    #=> [1, -1, nil, nil, 5, 4, -3, nil, nil, 1]

    Enum.take(StreamData.nullable(StreamData.integer(), ratio: 0.25), 10)
    #=> [1, nil, -3, nil, 3, -3, 0, 3, nil, nil]

    Enum.take(StreamData.nullable(StreamData.integer(), ratio: 0.25), 10)
    #=> [0, -2, 1, nil, -2, 0, -4, 4, 6, nil]

    Enum.take(StreamData.nullable(StreamData.boolean(), ratio: 0.25), 10)
    #=> [false, false, false, nil, true, true, true, false, false, true]

# `one_of`

```elixir
@spec one_of([t(a)]) :: t(a) when a: term()
```

Generates values out of one of the given `datas`.

`datas` must be a list of generators. The values generated by this generator
are values generated by generators in `datas`, chosen each time at random.

## Examples

    data = StreamData.one_of([StreamData.integer(), StreamData.binary()])
    Enum.take(data, 3)
    #=> [-1, <<28>>, ""]

## Shrinking

This generator first shrinks towards earlier generators in `datas`, and then
shrinks the generated value according to the generator that generated it.

# `optional_map`

```elixir
@spec optional_map(map() | keyword(), [any()] | nil) :: t(map())
```

Generates maps with fixed but optional keys and generated values.

`data_map` is a map or keyword list of `fixed_key => data` pairs. Maps generated by this
generator will have a subset of the keys of `data_map` and values corresponding to the values
generated by the generator unders those keys.

By default, all keys are considered optional. A list of exactly which keys are optional can be
provided as the second argument, allowing for a map of mixed optional and required keys. The second argument is available since StreamData 0.6.0.

See also `fixed_map/1`.

## Examples

    data = StreamData.optional_map(%{
      integer: StreamData.integer(),
      binary: StreamData.binary(),
    })
    Enum.take(data, 3)
    #=> [%{binary: "", integer: 1}, %{integer: -2}, %{binary: "R1^"}]

    data = StreamData.optional_map(%{
      integer: StreamData.integer(),
      binary: StreamData.binary(),
    }, [:integer])
    Enum.take(data, 3)
    #=> [%{binary: ""}, %{binary: "R1^", integer: -2}, %{binary: "R2^"}]

## Shrinking

This generator shrinks by first shrinking the map by taking out keys until the map is empty, and
then by shrinking the generated values.

# `positive_integer`

```elixir
@spec positive_integer() :: t(pos_integer())
```

Generates positive integers bound by the generation size.

## Examples

    Enum.take(StreamData.positive_integer(), 3)
    #=> [1, 1, 3]

## Shrinking

Generated values shrink towards `1`.

# `repeatedly`
*since 0.6.0* 

```elixir
@spec repeatedly((-&gt; returns)) :: t(returns) when returns: term()
```

Calls the provided zero argument function to generate values.

## Examples

Generating a UUID

    uuid = StreamData.repeatedly(&Ecto.UUID.generate/0)
    Enum.take(uuid, 3)
    #=> ["2712ec5b-bc50-4b4a-8a8a-ca85d37a457b", "2092570d-8fb0-4e67-acbe-92db4c8a2bae", "1bef1fb1-8f86-46ac-a49e-3bffaa51e40b"]

Generating a unique integer

    integer = StreamData.repeatedly(&System.unique_integer([:positive, :monotonic]))
    Enum.take(integer, 3)
    #=> [1, 2, 3]

## Shrinking

By nature, this generator is not shrinkable.

# `resize`

```elixir
@spec resize(t(a), size()) :: t(a) when a: term()
```

Resize the given generated `data` to have fixed generation size `new_size`.

The new generator will ignore the generation size and always use `new_size`.

See the "Generation size" section in the documentation for `StreamData` for
more information about the generation size.

## Examples

    data = StreamData.resize(StreamData.integer(), 10)
    Enum.take(data, 3)
    #=> [4, -5, -9]

# `scale`

```elixir
@spec scale(t(a), (size() -&gt; size())) :: t(a) when a: term()
```

Scales the generation size of the given generator `data` according to
`size_changer`.

When generating data from `data`, the generation size will be the result of
calling `size_changer` with the generation size as its argument. This is
useful, for example, when a generator needs to grow faster or slower than
the default.

See the "Generation size" section in the documentation for `StreamData` for
more information about the generation size.

## Examples

Let's create a generator that generates much smaller integers than `integer/0`
when size grows. We can do this by scaling the generation size to the
logarithm of the generation size.

    data = StreamData.scale(StreamData.integer(), fn size ->
      trunc(:math.log(size))
    end)

    Enum.take(data, 3)
    #=> [0, 0, -1]

Another interesting example is creating a generator with a fixed maximum
generation size. For example, say we want to generate binaries but we never
want them to be larger than 64 bytes:

    small_binaries = StreamData.scale(StreamData.binary(), fn size ->
      min(size, 64)
    end)

# `seeded`

```elixir
@spec seeded(t(a), integer()) :: t(a) when a: term()
```

Makes the given generator `data` always use the same given `seed` when generating.

This function is useful when you want a generator to have a predictable generating
behaviour. It's especially useful when using a generator with the `Enumerable` protocol
since you can't set the seed specifically in that case (while you can with `check_all/3`
for example).

`seed` must be an integer.

## Examples

    int = StreamData.seeded(StreamData.integer(), 10)

    Enum.take(int, 3)
    #=> [-1, -2, 1]
    Enum.take(int, 4)
    #=> [-1, -2, 1, 2]

# `shuffle`
*since 1.2.0* 

```elixir
@spec shuffle(Enumerable.t()) :: t(Enumerable.t())
```

Generates *lists* with the same elements as the provided `enum` but in a random order.

## Examples

    StreamData.shuffle([1, 2, 3, 4, 5])
    |> Enum.take(3)
    #=> [[4, 2, 5, 3, 1], [1, 3, 4, 5, 2], [3, 2, 5, 4, 1]]

## Shrinking

Shrinks towards a list with elements in the same order as the original `enum`.

# `sized`

```elixir
@spec sized((size() -&gt; t(a))) :: t(a) when a: term()
```

Returns the generator returned by calling `fun` with the generation size.

`fun` takes the generation size and has to return a generator, that can use
that size to its advantage.

See the "Generation size" section in the documentation for `StreamData` for
more information about the generation size.

## Examples

Let's build a generator that generates integers in double the range `integer/0`
does:

    data = StreamData.sized(fn size ->
      StreamData.resize(StreamData.integer(), size * 2)
    end)

    Enum.take(data, 3)
    #=> [0, -1, 5]

## Shrinking

Generation size itself **does not shrink**. Any constraints derived from it
stay in place while shrinking the generated value. For example, a list
generated with `min_length: size` cannot shrink below the size used for that
run. In this example, if the intent is to generate a list with up to `size`
elements that can shrink to an empty list, use `list_of/1` directly or pass
`max_length: size` instead.

# `string`

Generates a string of the given kind or from the given characters.

`kind_or_codepoints` can be:

  * `:ascii` - strings containing only ASCII characters are generated. Such
    strings shrink towards lower codepoints.

  * `:alphanumeric` - strings containing only alphanumeric characters
    (`?a..?z`, `?A..?Z`, `?0..?9`) are generated. Such strings shrink towards
    `?a` following the order shown previously.

  * `:printable` - printable strings (`String.printable?/1` returns `true`)
    are generated. Such strings shrink towards lower codepoints.

  * `:utf8` - valid strings (`String.valid?/1` returns `true`)
    are generated. Such strings shrink towards lower codepoints. *Available
    since 0.6.0.*

  * a range - strings with characters from the range are generated. Such
    strings shrink towards characters that appear earlier in the range.

  * a list of ranges or single codepoints - strings with characters from the
    ranges or codepoints are generated. Such strings shrink towards earlier
    elements of the given list and towards the beginning of ranges.

## Options

This function accepts the same length-related options as `list_of/2`
(`:length`, `:min_length`, and `:max_length`), plus:

  * `:count` - (`:codepoints` or `:graphemes`) controls what the
    length-related options count. Defaults to `:codepoints`.

    * `:codepoints` - the length-related options count the number of
      Unicode codepoints in the generated string. This is what `list_of/2`
      counts under the hood, and it is the default for backwards
      compatibility.

    * `:graphemes` - the length-related options count the number of
      graphemes in the generated string, that is, what `String.length/1`
      returns. This matters for kinds such as `:printable` and `:utf8`,
      which can generate combining characters: a base character followed
      by a combining mark is two codepoints but a single grapheme. Without
      this option, `String.length/1` of a generated string can be *smaller*
      than the requested minimum length. *Available since 1.4.0.*

## Examples

    Enum.take(StreamData.string(:ascii), 3)
    #=> ["c", "9A", ""]

    Enum.take(StreamData.string(Enum.concat([?a..?c, ?l..?o])), 3)
    #=> ["c", "oa", "lb"]

## Shrinking

Shrinks towards smaller strings and as described in the description of the
possible values of `kind_or_codepoints` above.

# `term`

```elixir
@spec term() :: t(simple | [simple] | %{optional(simple) =&gt; simple} | tuple())
when simple: boolean() | integer() | binary() | float() | atom() | reference()
```

Generates any term.

The terms that this generator can generate are simple terms or compound terms. The simple terms
are:

  * integers (through `integer/0`)
  * binaries (through `binary/1`)
  * floats (through `float/0`)
  * booleans (through `boolean/0`)
  * atoms (through `atom/1`)
  * references (which are not shrinkable)

Compound terms are terms that contain other terms (which are generated recursively with
`term/0`):

  * lists (through `list_of/2`)
  * maps (through `map_of/2`)
  * tuples

## Examples

    Enum.take(StreamData.term(), 3)
    #=> [0.5119003572251588, {{true, ""}}, :WJg]

## Shrinking

The terms generated by this generator shrink based on the generator used to create them (see the
list of possible generated terms above).

# `tree`

```elixir
@spec tree(t(a), (child_data :: t(a | b) -&gt; t(b))) :: t(a | b)
when a: term(), b: term()
```

Generates trees of values generated by `leaf_data` and `subtree_fun`.

`leaf_data` generates the leaf nodes. `subtree_fun` is a function that is
called by `tree`, if an inner node of the tree shall be generated. It takes a
generator `child_gen` for child nodes and returns a generator for an inner
node using `child_gen` to go "one level deeper" in the tree. The frequency
between leaves and inner nodes is 1:2.

This is best explained with an example. Say that we want to generate binary
trees of integers, and that we represent binary trees as either an integer (a
leaf) or a `%Branch{}` struct:

    defmodule Branch do
      defstruct [:left, :right]
    end

Now, we can generate trees by using the `integer()` generator to generate
the leaf nodes. Then we can use the `subtree_fun` function to generate inner
nodes (that is, `%Branch{}` structs or `integer()`s).

    tree_data =
      StreamData.tree(StreamData.integer(), fn child_data ->
        StreamData.map({child_data, child_data}, fn {left, right} ->
          %Branch{left: left, right: right}
        end)
      end)

    Enum.at(StreamData.resize(tree_data, 10), 0)
    #=> %Branch{left: %Branch{left: 4, right: -1}, right: -2}

## Examples

A common example is a nested list:

    data = StreamData.tree(StreamData.integer(), &StreamData.list_of/1)
    Enum.at(StreamData.resize(data, 10), 0)
    #=> [[], '\t', '\a', [1, 2], -3, [-7, [10]]]

A more complex example is generating data that could represent the Elixir
equivalent of a JSON document. The code below is slightly simplified
compared to the JSON spec.

    scalar_generator =
      StreamData.one_of([
        StreamData.integer(),
        StreamData.boolean(),
        StreamData.string(:ascii),
        nil
      ])

    json_generator =
      StreamData.tree(scalar_generator, fn nested_generator ->
        StreamData.one_of([
          StreamData.list_of(nested_generator),
          StreamData.map_of(StreamData.string(:ascii, min_length: 1), nested_generator)
        ])
      end)

    Enum.at(StreamData.resize(json_generator, 10), 0)
    #=> [%{"#" => "5"}, true, %{"4|B" => nil, "7" => true, "yt(3y" => 4}, [[false]]]

## Shrinking

Shrinks values and shrinks towards less deep trees.

# `tuple`

```elixir
@spec tuple(tuple()) :: t(tuple())
```

Generates tuples where each element is taken out of the corresponding
generator in the `tuple_datas` tuple.

## Examples

    data = StreamData.tuple({StreamData.integer(), StreamData.binary()})
    Enum.take(data, 3)
    #=> [{-1, <<170>>}, {1, "<"}, {1, ""}]

## Shrinking

Shrinks by shrinking each element in the generated tuple according to the
corresponding generator.

# `uniq_list_of`

```elixir
@spec uniq_list_of(
  t(a),
  keyword()
) :: t([a])
when a: term()
```

Generates a list of elements generated by `data` without duplicates (possibly
according to a given uniqueness function).

This generator will generate lists where each list is unique according to the
value returned by applying the given uniqueness function to each element
(similarly to how `Enum.uniq_by/2` works). If more than the value of the
`:max_tries` option consecutive elements are generated that are considered
duplicates according to the uniqueness function, a
`StreamData.TooManyDuplicatesError` error is raised. For this reason, try to
make sure to not make the uniqueness function return values out of a small
value space. The uniqueness function and the max number of tries can be
customized via options.

## Options

  * `:uniq_fun` - (a function of arity one) a function that is called with
    each generated element and whose return value is used as the value to
    compare with other values for uniqueness (similarly to `Enum.uniq_by/2`).

  * `:max_tries` - (non-negative integer) the maximum number of times that
    this generator tries to generate the next element of the list before
    giving up and raising a `StreamData.TooManyDuplicatesError` in case it
    can't find a unique element to generate. Note that the generation size
    often affects this: for example, if you have a generator like
    `uniq_list_of(integer(), min_length: 4)` and you start generating elements
    out of it with a generation size of `1`, it will fail by definition
    because `integer/0` generates in `-size..size` so it would only generate
    in a set (`[-1, 0, 1]`) with three elements. Use `resize/2` or `scale/2`
    to manipulate the size (for example by setting a minimum generation size
    of `3`) in such cases.

  * `:length` - (non-negative integer) same as in `list_of/2`.

  * `:min_length` - (non-negative integer) same as in `list_of/2`.

  * `:max_length` - (non-negative integer) same as in `list_of/2`.

## Examples

    data = StreamData.uniq_list_of(StreamData.integer())
    Enum.take(data, 3)
    #=> [[1], [], [2, 3, 1]]

## Shrinking

This generator shrinks like `list_of/1`, but the shrunk values are unique
according to the `:uniq_fun` option as well.

# `unshrinkable`

```elixir
@spec unshrinkable(t(a)) :: t(a) when a: term()
```

Makes the values generated by `data` not shrink.

## Examples

Let's build a generator of bytes (integers in the `0..255`) range. We can
build this on top of `integer/1`, but for our purposes, it doesn't make sense for
a byte to shrink towards `0`:

    byte = StreamData.unshrinkable(StreamData.integer(0..255))
    Enum.take(byte, 3)
    #=> [190, 181, 178]

## Shrinking

The generator returned by `unshrinkable/1` generates the same values as `data`,
but such values will not shrink.

---

*Consult [api-reference.md](api-reference.md) for complete listing*
