I was playing with scalaz and thought I could extend Enum
type class for something to make myself understand scalaz better. So I wrote this:
sealed abstract trait Counter
case object First extends Counter
case object Second extends Counter
case object Third extends Counter
implicit val enumCounter: Enum[Counter] = new Enum[Counter] {
override def succ(a: Counter): Counter = a match {
case First => Second
case Second => Third
case Third => First
}
override def pred(a: Counter): Counter = a match {
case First => Third
case Second => First
case Third => Second
}
override def order(x: Counter, y: Counter): Ordering = {
val map = Map[Counter, Int](First -> 0, Second -> 1, Third -> 2)
implicitly[Order[Int]].order(map(x), map(y))
}
}
println(First |=> Third)
println(First.succ)
But it turns out that it doesn't work as I hoped it will. First
does not have succ
nor |=>
, because I've created Enum[Counter]
but not Enum[First]
. If I write First.asInstanceOf[Counter].succ
it starts to resolve. Which is now obvious to me. But how can I implement Enum
typeclass then in a simple way? I do not want to declare separate implicit values for each of Enum[First]
, Enum[Second]
....
There are two possible solutions I am thinking of:
1) Make scala resolve Enum[First]
as Enum[Counter]
. But I cannot seem to understand how this can be possible as Enum
can be only nonvariant
2) Maybe there is a solution in scalaz?
Otherwise Enum
typeclass starts to be quite limited, as it does not supports Enum which sounds very weird.
I am actually not sure how much this question belongs to scalaz
, it probably depends on whether the solution is (1) or (2). If the solution is (1) - this question is pure scala.