title: Mixing contravariant and covariant types in Scala
body: <p>I am trying to build a framework with a hierarchy of <code>Context</code>s (that hold immutable data) and <code>Module</code>s that create actors work with the data.  Subclasses on <code>Context</code> include more data (e.g., a <code>RemoteContext</code> would have information about how to communicate with remote hosts).  There are also <code>Factory</code> objects to make the relevant objects, which is part of the data in the <code>Context</code>.  </p>
  
  <p>I can define the hierarchy with sub-classes, and that works fine.  Once everything is defined, a <code>Mediator</code> object initializes each <code>Module</code> by passing the context.</p>
  
  <p>The code below shows that basic structure.</p>
  
  <pre><code>import java.{ util =&gt; ju}
  
  trait Factory
  trait Context[F &lt;: Factory]
  
  trait SomeContext[F &lt;: Factory] extends Context[F]
  
  trait MediatorModule[C &lt;: Context[_ &lt;: Factory]] {
      def loadModule(c: C)
  }
  
  trait Mediator[C &lt;: Context[Factory]] {
      val context: C
      def getModules: ju.List[MediatorModule[_ &gt;: C]]
      def run() = getModules.forEach(_.loadModule(context))
  }
  
  trait OtherFact extends Factory
  trait OtherContext extends SomeContext[OtherFact]
  
  class SomeModule extends MediatorModule[SomeContext[Factory]] {
      def loadModule(c: SomeContext[Factory]): Unit = { }
  }
  class OtherModule extends MediatorModule[OtherContext] {
      def loadModule(c: OtherContext): Unit = { }
  }
  
  class OtherContextImpl extends OtherContext {
  
  }
  
  class OtherMediator extends Mediator[OtherContext] {
      val context: OtherContext = new OtherContextImpl
      def getModules: ju.List[MediatorModule[_ &gt;: OtherContext]] =
          ju.Arrays.asList(new SomeModule,
                           new OtherModule)
  }
  </code></pre>
  
  <p>(The code was originally written in Java, which is why it is using Java lists).</p>
  
  <p>As written, this fails to compile:</p>
  
  <pre><code>Test.scala:78:26: type mismatch;
  [error]  found   : SomeModule
  [error]  required: MediatorModule[_ &gt;: OtherContext]
  [error] Note: SomeContext[Factory] &lt;: Any (and SomeModule &lt;: MediatorModule[SomeContext[Factory]]), but trait MediatorModule is invariant in type C.
  [error] You may wish to define C as +C instead. (SLS 4.5)
  [error]         ju.Arrays.asList(new SomeModule,
  [error]                          ^
  [error] one error found
  </code></pre>
  
  <p>Following the compiler's suggestion by declaring <code>trait MediatorModule[+C &lt;: Context[_ &lt;: Factory]]</code> instead gives two errors:</p>
  
  <pre><code>Test.scala:52:20: covariant type C occurs in contravariant position in type C of value c
  [error]     def loadModule(c: C)
  [error]                    ^
  [error] Test.scala:75:29: type arguments [OtherContext] do not conform to trait Mediator's type parameter bounds [C &lt;: Context[Factory]]
  [error] class OtherMediator extends Mediator[OtherContext] {
  [error]                             ^
  
  </code></pre>
  
  <p>I can fix one with <code>trait Context[+F &lt;: Factory]</code> but the co/contra variant error remains.</p>
  
  <p>What can I do to fix that error?  Also, how does <code>+C</code> translate back to Java?</p>