lib/tyyppi/valuable.ex

defmodule Tyyppi.Valuable do
  @moduledoc """
  The behaviour all participants of the `Tyyppi`’s operations
    should have implemented.

  It’s implemented by `Tyyppi.Value` and `Tyyppi.Struct`, making them available
    for deep nested validations, coercion and generation.
  """

  @typedoc "Type of the value behind the implementation"
  @type value :: any()

  @typedoc """
  Type returned from coercions and validations, typical pair of ok/error tuples,
    involving the `value()` as a main type behind
  """
  @type either :: {:ok, value()} | {:error, any()}

  @typedoc """
  Type of the generation function, basically returning a stream of generated values
  """
  if StreamData == Tyyppi.Value.Generations.prop_test() do
    @type generation :: StreamData.t(value())
  else
    @type generation :: Enumerable.t()
  end

  ##############################################################################

  @doc """
  The validation function, receiving the `value()`
  """
  @callback validate(value()) :: either()

  @doc """
  The coercion function, receiving the `value()`
  """
  @callback coerce(value()) :: either()

  @doc """
  The generation function, returning the generator for the whole
  """
  @callback generation(value()) :: generation()

  @doc """
  Flattens the struct using the options passed
  """
  @callback flatten(value(), keyword()) :: value()
end