型クラス中級講座 

Haskell の文法に関しては飛ばして第8章の型や型クラスを自分で作ろう まで行こう (本を持っている人は第7章)。

信号の型クラス 

data TrafficLight = Red | Yellow | Green

これを Scala で書くと:

scala> :paste
// Entering paste mode (ctrl-D to finish)

sealed trait TrafficLight
case object Red extends TrafficLight
case object Yellow extends TrafficLight
case object Green extends TrafficLight

これに Equal のインスタンスを定義する。

scala> implicit val TrafficLightEqual: Equal[TrafficLight] = Equal.equal(_ == _)
TrafficLightEqual: scalaz.Equal[TrafficLight] = scalaz.Equal$$anon$7@2457733b

使えるかな?

scala> Red === Yellow
<console>:18: error: could not find implicit value for parameter F0: scalaz.Equal[Product with Serializable with TrafficLight]
              Red === Yellow

Equal が不変 (invariant) なサブタイプ Equal[F] を持つせいで、Equal[TrafficLight] が検知されないみたいだ。TrafficLight を case class にして RedYellow が同じ型を持つようになるけど、厳密なパターンマッチングができなくなる。#ダメじゃん

scala> :paste
// Entering paste mode (ctrl-D to finish)

case class TrafficLight(name: String)
val red = TrafficLight("red")
val yellow = TrafficLight("yellow")
val green = TrafficLight("green")
implicit val TrafficLightEqual: Equal[TrafficLight] = Equal.equal(_ == _)
red === yellow

// Exiting paste mode, now interpreting.

defined class TrafficLight
red: TrafficLight = TrafficLight(red)
yellow: TrafficLight = TrafficLight(yellow)
green: TrafficLight = TrafficLight(green)
TrafficLightEqual: scalaz.Equal[TrafficLight] = scalaz.Equal$$anon$7@42988fee
res3: Boolean = false