Field-level Elixir input validation with error maps

Elixir
defmodule InputValidation do
  @rules %{
    name: &(is_binary(&1) and String.length(&1) in 2..50),
    email: &(is_binary(&1) and String.contains?(&1, "@")),
    age: &(is_integer(&1) and &1 in 18..130)
  }

  def validate(params, rules \\ @rules) do
    errors =
      Enum.reduce(rules, %{}, fn {field, check}, acc ->
        case Map.fetch(params, field) do
          :error -> Map.put(acc, field, "is required")
          {:ok, value} -> if check.(value), do: acc, else: Map.put(acc, field, "is invalid")
        end
      end)

    if map_size(errors) == 0, do: {:ok, params}, else: {:error, errors}
  end
end