1

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.

Archeg
  • 8,364
  • 7
  • 43
  • 90
  • Looks like you're basically doing what the scalaz example digit does:https://github.com/scalaz/scalaz/blob/series/7.3.x/core%2Fsrc%2Fmain%2Fscala%2Fscalaz%2FDigit.scala – Noah Jan 22 '16 at 23:00
  • To get around the issue you would do something like `(First: Counter)` from the examples similar usage https://github.com/scalaz/scalaz/blob/series/7.3.x/example%2Fsrc%2Fmain%2Fscala%2Fscalaz%2Fexample%2FEnumUsage.scala – Noah Jan 22 '16 at 23:01
  • @Noah Thanks for the response. Type ascription is something I wanted to avoid. But it appears that scalaz is designed so it is not possible to do the stuff I want. I've asked the same question second time - while rephrasing a lot, and I've got an answer, if you are interested - please see this: http://stackoverflow.com/questions/34907387/typeclasses-and-inheritance-in-scalaz In short the solution is very alike type ascription, but the idea is to encapsulate it in methods, and this is how it is done in scalaz itself. Haskell does it much better, but it is impossible in scala – Archeg Jan 22 '16 at 23:39

1 Answers1

0

I rethought the question and rephrased it a lot - and received an answer, please see this: Typeclasses and inheritance in scalaz

Community
  • 1
  • 1
Archeg
  • 8,364
  • 7
  • 43
  • 90