An Elixir library for defining types and schemas by composing refinement functions.
You can define new types and schemas using the Refinex DSL:
defmodule String do
use Refinex
type()
refine(:is_binary)
end
defmodule Integer do
use Refinex
type()
refine(:is_integer)
end
defmodule List do
use Refinex
type([:item])
refine(:is_list)
refine(:validate_items)
def validate_items(list, [item]) do
list
|> Enum.map(&Refinex.is?(&1, item))
|> Enum.all?()
end
end
defmodule Person do
use Refinex
schema(name: String, age: Integer, friends: List.of(Person))
refine(:is_adult)
def is_adult(person) do
person.age >= 18
end
endOnce defined, you can validate any Elixir term against these type and schema definitions.
iex> Refinex.is?("elixir", String)
true
iex> Refinex.is?(:elixir, String)
false
iex> Refinex.is?([], List.of(String))
true
iex> Refinex.is?(["elixir", "erlang"], List.of(String))
true
iex> Refinex.is?(["elixir", :erlang], List.of(String))
false
iex> Refinex.is?(%{"name" => "John Doe", "age" => 30, friends => []}, Person)
true
iex> Refinex.is?(%{"name" => "John Doe", "age" => 30, "friends" => [%{"name" => "Mary Sue", "age" => 32, "friends" => []}]}, Person)
true
iex> Refinex.is?(%{}, Person)
falseIf you would like more descriptive errors as to why a term failed refinement:
iex> Refinex.check("elixir", String)
{:ok, "elixir"}
iex> Refinex.check(:elixir, String)
{:error, [%Refinex.Error{message: ":elixir failed refinement for Kernel.is_string/1"}]}Add the following to your mix.exs file:
def deps do
[
{:refinex, "~> 0.1.0"}
]
end