@type caster() :: :string | :string? | :string! | :atom | :atom? | :atom! | :existing_atom | :existing_atom? | :existing_atom! | :boolean | :boolean! | :boolean? | :integer! | :integer? | :integer | :float! | :float? | :float | (term() -> result())
@type result() :: {:ok, term()} | {:error, String.t()} | {:error, :empty} | {:error, :bad_cast}
@spec cast(term(), caster()) :: result()