我正在翻译Scala中https://sebfisch.github.io/haskell-regexp/regexp-play.pdf中的Haskell代码以进行自学。 我以这种方式翻译了“类Semiring”(第2页):
trait Semiring[S] {
def zero: S
def one: S
def add(a: S, b: S): S
def mult(a: S, b: S): S
}
以及与此相关的类SemiringI(第7页):
trait SemiringI[S] extends Semiring[S] {
def index: Int => S
}
然后我必须提供特定类型参数的实例,因此我尝试以我认为是规范的方式进行操作,即将它们定义为隐式val。
implicit val semiringLeftmost = new Semiring[LeftmostT] {
// ...implementation of zero, one, add, mult...
}
但是,当我必须为LeftmostT定义SemiringI实例时遇到一些问题:
implicit val semiringILeftmost = new SemiringI[LeftmostT] {
// ...implementation of zero, one, add, mult (same as for Semiring[LeftmostT])
// ...implementation of index
}
在我看来,我不得不重复在Semiring [LeftmostT]中已经定义的功能的实现,当然,这些功能是不可扩展的。 我在网上搜索了答案,但是找不到。 例如,在https://www.slideshare.net/jdegoes/scalaz-8-a-whole-new-game(幻灯片7)中,MonoididInt不会像我期望的那样重用Semigroup的append定义。
最后,我设法找到了一种进行方法,即:
// traits Semiring[S] and SemiringI[S] defined as above
class semiringLeftmostC extends Semiring[LeftmostT] {
// ...implementation of zero, one, add, mult...
}
implicit val semiringLeftmost = new semiringLeftmostC()
class semiringILeftmostC extends semiringLeftmostC with SemiringI[LeftmostT] {
// ...implementation of index
}
implicit val semiringILeftmost = new semiringILeftmostC()
但是我不确定这是最好的。 有人可以告诉我是否还有其他可能性可以达到相同的目标,即在类型类实例的层次结构中重用代码?
谢谢。