# credo:disable-for-this-file defmodule Funx.Monoid.Ord do @moduledoc """ A monoid implementation for ordering logic (Ord). Provides default comparison functions and supports combining multiple `Ord` comparators into a single composite comparator. """ @type t :: %__MODULE__{ lt?: (any(), any() -> boolean()), le?: (any(), any() -> boolean()), gt?: (any(), any() -> boolean()), ge?: (any(), any() -> boolean()) } defstruct lt?: &Funx.Monoid.Ord.default?/2, le?: &Funx.Monoid.Ord.default?/2, gt?: &Funx.Monoid.Ord.default?/2, ge?: &Funx.Monoid.Ord.default?/2 def default?(_, _), do: false end defimpl Funx.Monoid, for: Funx.Monoid.Ord do alias Funx.Monoid.Ord alias Funx.Ord.Utils @spec empty(any()) :: Ord.t() def empty(_) do %Ord{} end @spec append(Ord.t(), Ord.t()) :: Ord.t() def append(%Ord{} = ord1, %Ord{} = ord2) do %Ord{ lt?: fn a, b -> cond do ord1.lt?.(a, b) -> true ord1.gt?.(a, b) -> false true -> ord2.lt?.(a, b) end end, le?: fn a, b -> cond do ord1.lt?.(a, b) -> true ord1.gt?.(a, b) -> false true -> ord2.le?.(a, b) end end, gt?: fn a, b -> cond do ord1.gt?.(a, b) -> true ord1.lt?.(a, b) -> false true -> ord2.gt?.(a, b) end end, ge?: fn a, b -> cond do ord1.gt?.(a, b) -> true ord1.lt?.(a, b) -> false true -> ord2.ge?.(a, b) end end } end def wrap(%Ord{}, ord) do ord = Utils.to_ord_map(ord) %Ord{ lt?: ord.lt?, le?: ord.le?, gt?: ord.gt?, ge?: ord.ge? } end @spec unwrap(Ord.t()) :: map() def unwrap(%Ord{lt?: lt?, le?: le?, gt?: gt?, ge?: ge?}) do %{ lt?: lt?, le?: le?, gt?: gt?, ge?: ge? } end end