Elixir:如何使自定义类型实现 ==、< 和 >
Elixir: how to make a custom type implement ==, <, and >
背景:我正在努力将这个 F# discriminated union 转换为 Elixir:
type Suit =
| Diamonds
| Clubs
| Hearts
| Spades
我知道有几种不同的方法可以做到这一点,这不是我的问题。
以下必须为真:
Diamonds == Diamonds
Diamonds < Hearts
Spades > Hearts
我很惊讶地发现 Elixir 没有类似于 Haskell 的 Ord
类型类和 GitHub 上的 implementation 的类似协议(非常几颗星!)
是否有一种广为接受或惯用的方法来使自定义类型具有可比性?
执行此操作的惯用方法是在定义自定义类型的模块中简单地提供 equal?/2
and/or compare/2
。这可以在核心库和强大的第三方库中经常看到。
例如,Date.compare/2
具有以下规格
compare(Calendar.date(), Calendar.date()) :: :lt | :eq | :gt
从 v1.10.0
开始,Elixir 为实现 compare/2
:
的结构提供方便的 Enum.sort/2
排序
defmodule User do
defstruct [:name]
def compare(%User{name: n1}, %User{name: n2}) when n1 < n2,
do: :lt
def compare(%User{name: n1}, %User{name: n2}) when n1 > n2,
do: :gt
def compare(%User{}, %User{}), do: :eq
end
users = [
%User{name: "john"},
%User{name: "joe"},
%User{name: "jane"}
]
Enum.sort(users, {:asc, User})
#⇒ [%User{name: "jane"},
# %User{name: "joe"},
# %User{name: "john"}]
背景:我正在努力将这个 F# discriminated union 转换为 Elixir:
type Suit =
| Diamonds
| Clubs
| Hearts
| Spades
我知道有几种不同的方法可以做到这一点,这不是我的问题。
以下必须为真:
Diamonds == Diamonds
Diamonds < Hearts
Spades > Hearts
我很惊讶地发现 Elixir 没有类似于 Haskell 的 Ord
类型类和 GitHub 上的 implementation 的类似协议(非常几颗星!)
是否有一种广为接受或惯用的方法来使自定义类型具有可比性?
执行此操作的惯用方法是在定义自定义类型的模块中简单地提供 equal?/2
and/or compare/2
。这可以在核心库和强大的第三方库中经常看到。
例如,Date.compare/2
具有以下规格
compare(Calendar.date(), Calendar.date()) :: :lt | :eq | :gt
从 v1.10.0
开始,Elixir 为实现 compare/2
:
Enum.sort/2
排序
defmodule User do
defstruct [:name]
def compare(%User{name: n1}, %User{name: n2}) when n1 < n2,
do: :lt
def compare(%User{name: n1}, %User{name: n2}) when n1 > n2,
do: :gt
def compare(%User{}, %User{}), do: :eq
end
users = [
%User{name: "john"},
%User{name: "joe"},
%User{name: "jane"}
]
Enum.sort(users, {:asc, User})
#⇒ [%User{name: "jane"},
# %User{name: "joe"},
# %User{name: "john"}]