Question

I am trying to put a type family imitation to use in a pattern where a typeclass instance depends on a type resolved by another typeclass instance, which is presented in the following block:

( implicit someTypeResolver: SomeTypeResolver[ a ],
           stringRep: StringRep[ someTypeResolver.SomeType ] )

where you can see the stringRep resolution being dependant on the resolution of someTypeResolver.

Here's the complete source

// A typeclass, 
// which is basically just a type-function from type `a` to `SomeType`
trait SomeTypeResolver[ a ] {
  type SomeType
}
object SomeTypeResolver {
  // An instance, which maps type `Int` to `Boolean`
  implicit val int = new SomeTypeResolver[ Int ]{ type SomeType = Boolean }
  // An instance, which maps type `Char` to `String`
  implicit val char = new SomeTypeResolver[ Char ]{ type SomeType = String }
}

// A simple typeclass which maps a type to some string representation
trait StringRep[ a ] {
  val string: String
}
object StringRep {
  implicit val boolean = new StringRep[ Boolean ]{ val string = "I'm a bool" }
  implicit val char = new StringRep[ Char ]{ val string = "I'm a char" }
}

// Having the following function, which is supposed to return a string 
// representation of a type, which `a` is mapped to
def resolve
  [ a ]
  ( implicit someTypeResolver: SomeTypeResolver[ a ],
             stringRep: StringRep[ someTypeResolver.SomeType ] )
  = stringRep.string

// I expect it to behave like so
assert( resolve[ Int ] == "I'm a bool" )
assert( resolve[ Char ] == "I'm a char" )

But the above fails to compile with the following message:

illegal dependent method type: parameter appears in the type of another parameter in the same section or an earlier one

How to approach this?

No correct solution

OTHER TIPS

So, as the error states, we need to somehow move the stringRep resolution into another postponed section. To achieve this we can instantiate an intermediate object, which introduces this section in its apply function:

def resolve
  [ a ]
  ( implicit someTypeResolver: SomeTypeResolver[ a ] )
  = 
  new {
    def apply( implicit stringRep: StringRep[ someTypeResolver.SomeType ] ) =
      stringRep.string
  }

assert( resolve[ Int ].apply == "I'm a bool" )
assert( resolve[ Char ].apply == "I'm a string" )

It must be noted that with this approach, the user must explicitly call the apply function as shown in the assertions above.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top