Reputation: 3689
I've seen all the other answers to this exception but I don't think they solve my problem or may be I don't understand.
I'm trying to create a type class to extract out implementation of Command
s to CommandHandler
s
object TestMe extends App {
//COMMAND
trait Command
trait UserCommand extends Command
case class CreateUserCommand(username: String) extends UserCommand
//COMMAND HANDLER
trait CommandHandler[C <: Command] {
def processCommand(command: C): Boolean
}
trait UserCommandHandler[+C <: UserCommand] extends CommandHandler[C]
implicit object CreateUserCommandHandler extends UserCommandHandler[CreateUserCommand] {
override def processCommand(command: CreateUserCommand): Boolean = true
}
//Running UserCommand
def processCommand[C <: UserCommand](command: C)(implicit commandHandler: UserCommandHandler[C]) =
commandHandler.processCommand(command)
val createUserCommand: UserCommand = CreateUserCommand("username")
println(processCommand(createUserCommand))
}
But I keep getting the following exception
covariant type C occurs in invariant position in type [+C <: TestMe.Command]TestMe.CommandHandler[C] {
} of trait UserCommandHandler
trait UserCommandHandler[+C <: Command] extends CommandHandler[C]
^
Upvotes: 0
Views: 794
Reputation: 91
The type C in UserCommandHandler is covariant but the type C in CommandHandler is invariant, so you cant pass the C type from the UserCommandHandler to CommandHandler
So you have 2 options -
Type C in CommandHandler trait should also be covariant.
trait CommandHandler[+C <: Command] {
def processCommand[B >: C](command: B): Boolean
}
Type C in UserCommandHandler should be invariant
trait UserCommandHandler[C <: UserCommand] extends CommandHandler[C]
Looking at the rest of your code, invariance seems like its good enough. Making CommandHandler covariant will require other changes to your code as well
Upvotes: 1