Eq (Cats)
Eq
Eq
は等値性が定義されている型の集まりを表す型クラス。
- Eq
- Eq - cats-docs_2.13 2.12.0 javadoc
- cats/kernel/src/main/scala/cats/kernel/Eq.scala at v2.12.0 · typelevel/cats
cats の Eq
は eqv
メソッドが宣言されたトレイトとして定義されている。
1trait Eq[@sp A] extends Any with Serializable { self =>23def eqv(x: A, y: A): Boolean45def neqv(x: A, y: A): Boolean = !eqv(x, y)6}
neqv
は eqv
が返す真偽値とは逆の真偽値を返すメソッドとして定義されている。そのため、型の Eq
インスタンスを定義したい場合は eqv
メソッドだけ定義すればよい。しかし、Eq
はほとんどのデータ型 (ラムダ式のような比較不可能な値を持たないデータ型) について定義できるため、定義した型ごとに Eq
型クラスのインスタンスを実装しないといけない。それはかなり面倒な作業となるため、公式ドキュメントによると二つの方法が紹介されている。
一つは、公式ドキュメントに実装が載っている Eq.fromUniversalEquals
を使う方法。もう一つは、kittens という Cats を補助するライブラリを使う方法。それぞれ実際のコードは次のようになる。
1import cats.kernel.Eq23case class Point2D(x: Int, y: Int)45given Eq[Point2D] = Eq.fromUniversalEquals
kittens
を使うと derives Eq
だけで済むことがわかる。
Scala 3 から Haskell の deriving
相当のことができるようになっているため、
その機能を使って Eq
インスタンスが自動的に導出できる。
Eq
型クラスのインスタンスを定義すると eqv
、eqnv
のエイリアスとして ===
と =!=
が使えるようになる 1。これらの演算子 2 は equals
メソッドと異なり、比較対象がどちらも同じ型でなければならない。
Java 由来の equals
では、メソッドの引数が Any
となってしまっているため、異なる型の値を比較するようなコードを書いてしまった場合にコンパイラは警告を出力するがコンパイル自体は成功してしまう。異なる型を比較したい場面というのはほとんどないため、多くの場合そのようなコードはバグでしかない。そのため、Eq
型クラスによって提供される ===
、=!=
を使ってコンパイルエラーになるように書いておくことでより安全なコードとなる。
Eq
を使ったコードは EqTypeClassTest にある。
Eq
のシンタックス
https://github.com/typelevel/cats/blob/v2.12.0/core/src/main/scala/cats/syntax/eq.scala
型クラス | シンタックス | 説明 |
---|---|---|
Eq | === (eqv ) | 左辺と右辺が等値のとき true を返す。 |
Eq | =!= (eqnv ) | 左辺と右辺が等値ではないとき true を返す。 |
Footnotes
-
型クラスのインスタンスに対して使えるようになるメソッド、演算子は
cats.syntax
パッケージに定義されている。 ↩ -
Scala における演算子はメソッドの糖衣構文 (ref: 演算子 | Scala Documentation)。 ↩