2011年12月2日金曜日

Equal

Equalは型クラスです。
型クラスについては10日にやるScala会議で話す資料とか水島さんの死霊とか。

この型クラスは等しいという性質を与えます。

作り方

case class ScalaChan()
implicit def ScalaChanEqual: Equal[ScalaChan] = new Equal[ScalaChan] {
def equal(a1: ScalaChan, a2: ScalaChan): Boolean = a1 == a2
}
implicit def ScalaChanEqual: Equal[ScalaChan] = equal(_ == _)
implicit def ScalaChanEqual: Equal[ScalaChan] = equalA
assert(ScalaChan() === ScalaChan())
view raw e1.scala hosted with ❤ by GitHub

最初の方法はEqualのインスタンスを直接作るというもの。
二番目の方法はequalを使う方法。
equalは2つの値を受け取り、Booleanを返す述語を渡す。
三番目のequalAはequalをAnyの==を使って実装するというもの。
equalAとequalはEqualsに定義されており、Scalazがそれを継承しています。
この3つはどれも同じEqual[ScalaChan]が作られます。

Eqaulを利用した関数

===
/==

見た目通り等しい、等しくないを返す関数。
標準の==,!=と違うところは型安全というところ。

scala> 1 === 1
res39: Boolean = true
scala> 1 /== 1
res41: Boolean = false
scala> 1 /== 1L
<console>:23: error: type mismatch;
found : Long(1L)
required: Int
1 /== 1L
^
view raw e2.scala hosted with ❤ by GitHub

糖衣関数?もある。

assert("Scalaz" ≟ "Scalaz")
assert("Scalaちゃん" ≠ "Scalaz")
view raw e3.scala hosted with ❤ by GitHub

Equalだけを利用した関数が少なすぎて物悲しいのでもう一個

assert_===

Unit TestライブラリによくあるassertEqual的なもの。
エラーメッセージがちょっとかっこいい。
この関数は値がEqualの他にShowのインスタンスを持つことが必要です。

scala> "Scalaz" assert_=== "Scalaz"
scala> "Scalaちゃん" assert_=== "Scalaz"
java.lang.RuntimeException: Scalaちゃん ≠ Scalaz
at scalaz.Scalaz$.error_(Scalaz.scala:100)
at scalaz.Identity$class.assert_$eq$eq$eq(Identity.scala:32)
at scalaz.Identity$$anon$1.assert_$eq$eq$eq(Identity.scala:169)
.
.
.
.
scala> "Scalaちゃん" assert_≟ "Scalaちゃん"
view raw e4.scala hosted with ❤ by GitHub

基本的なEqualのインスタンスはEqualのコンパニオンオブジェクトに定義されています。
自分で定義したclassはequalやequalAでインスタンスを作っておきましょう。

0 件のコメント:

コメントを投稿