I am translating the Haskell code in https://sebfisch.github.io/haskell-regexp/regexp-play.pdf in Scala for self study. I translated "class Semiring" (page 2) in this way:

  trait Semiring[S] {
    def zero: S
    def one: S
    def add(a: S, b: S): S
    def mult(a: S, b: S): S

and the related class SemiringI (page 7) in this way:

  trait SemiringI[S] extends Semiring[S] {
    def index: Int => S

I had then to provide instances for specific type parameters, so I tried to proceed in what I think is the canonical way, i.e., defining them as implicit vals.

  implicit val semiringLeftmost = new Semiring[LeftmostT] {
    // ...implementation of zero, one, add, mult...

However, I had some problems when I had to define a SemiringI instance for LeftmostT:

  implicit val semiringILeftmost = new SemiringI[LeftmostT] {
    // ...implementation of zero, one, add, mult (same as for Semiring[LeftmostT])
    // ...implementation of index

It seemed to me I had to repeat the implementations of the functions already defined in Semiring[LeftmostT], that, of course, would not have been scalable. I searched the web for answers, but I was not able to find them. For example, in https://www.slideshare.net/jdegoes/scalaz-8-a-whole-new-game (slide 7) MonoidInt does not reuse the definition of append from Semigroup, as I expected.

At the end, I managed to find a way to proceed, namely:

  // 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()

but I am not sure it is the best one. Can someone please explain to me whether there are other possibilities to reach the same goals, i.e., reusing code in hierarchies of typeclass instances?

Thanks in advance.

0 Answers