【发布时间】:2016-01-15 23:32:38
【问题描述】:
我在玩 scalaz,并认为我可以扩展 Enum 类型类以使自己更好地理解 scalaz。所以我写了这个:
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)
但事实证明它并没有像我希望的那样工作。 First 没有succ 也没有|=>,因为我创建了Enum[Counter] 但没有Enum[First]。如果我写 First.asInstanceOf[Counter].succ 它开始解决。这对我来说是显而易见的。但是我怎样才能以简单的方式实现Enum typeclass?我不想为Enum[First]、Enum[Second] 中的每一个声明单独的隐式值....
我正在考虑两种可能的解决方案:
1) 让 scala 将 Enum[First] 解析为 Enum[Counter]。但我似乎无法理解这怎么可能,因为Enum 只能是不变的
2) scalaz 中是否有解决方案?
否则Enum typeclass 开始非常有限,因为它不支持 Enum,这听起来很奇怪。
我其实不确定这个问题在多大程度上属于scalaz,这可能取决于解决方案是(1)还是(2)。如果解决方案是 (1) - 这个问题是纯 scala。
【问题讨论】:
-
看起来你基本上在做scalaz示例数字所做的事情:github.com/scalaz/scalaz/blob/series/7.3.x/…
-
要解决这个问题,您可以从类似用法github.com/scalaz/scalaz/blob/series/7.3.x/… 的示例中执行类似
(First: Counter)的操作 -
@Noah 感谢您的回复。类型归属是我想避免的。但似乎 scalaz 被设计成不可能做我想做的事情。我第二次问了同样的问题 - 虽然改写了很多,我已经得到了答案,如果你有兴趣 - 请看这个:stackoverflow.com/questions/34907387/… 简而言之,解决方案是非常相似的类型归属,但想法是将其封装在方法中,这就是在 scalaz 本身中完成的方式。 Haskell 做得更好,但在 scala 中是不可能的