lib/matchers/predicate.ex

defmodule Matcher.Predicate do
  defstruct [:predicate]

  import Matcher.Errors

  defimpl Matcher.Protocol do
    def match(%{predicate: predicate}, actual, context) do
      if predicate.(actual) do
        {:ok, nil}
      else
        error(context, message: "mismatch: #{inspect(actual)} does not match the predicate")
      end
    end
  end
end