user438454534
user438454534

Reputation: 3689

Error: covariant type C occurs in invariant position in type?

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 Commands to CommandHandlers

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

Answers (1)

yogiHulk
yogiHulk

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 -

  1. Type C in CommandHandler trait should also be covariant.

    trait CommandHandler[+C <: Command] {
      def processCommand[B >: C](command: B): Boolean
    } 
    
  2. 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

Related Questions