Interdependent implicits and their use with type families

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?

Answers


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.


Need Your Help

Sum-aggregation script for term frequencies without dynamic scripting

elasticsearch groovy

I try to evaluate a web-application for my masterthesis. For this I want to make a user study, where I prepare the data in elasitc found, and send my web application to the testers. As far as I know,