lib/matchers/list.ex

defmodule Matcher.ListEquals do
  defstruct [:expected]

  defimpl Matcher.Protocol do
    def match(%{expected: expected}, actual) do
      Matcher.Utils.compare_lists(expected, actual)
    end
  end
end

defmodule Matcher.ListInAnyOrder do
  defstruct [:expected]

  defimpl Matcher.Protocol do
    def match(%{expected: expected}, actual) do
      matched =
        Matcher.Utils.permutations(expected)
        |> Enum.find(fn candidate ->
          Matcher.matches?(candidate, actual)
        end)

      if matched do
        {:ok, nil}
      else
        # TODO
        {:error, %{}}
      end
    end
  end
end

defimpl Matcher.Protocol, for: List do
  def match(expected, actual) do
    Matcher.match(%Matcher.ListEquals{expected: expected}, actual)
  end
end