title: How to subclass Scala immutable.Map with fixed type parameters?
body: <p>I can't figure out how to deal with overriding "+" in an immutable map if the map can only store an invariant type for its values.</p>
  
  <p>Something like:</p>
  
  <pre><code>class FixedMap(val impl : Map[String, Int])
      extends immutable.Map[String, Int] with immutable.MapLike[String, Int, FixedMap] {
      // This should return FixedMap if B1 is Int, and Map[String,B1]
      // if B1 is a superclass of Int; but there's no way to do that.
      // It is possible to return FixedMap here but then you have to
      // throw at runtime if B1 is not Int
      override def +[B1 &gt;: Int](kv : (String, B1)) : Map[String, B1] = {
          kv match {
              case (k, v : Int) =&gt;
                  new FixedMap(impl + Pair(k, v))
              case _ =&gt;
                  impl + kv
          }
      }
      // ...
  }
  </code></pre>
  
  <p>I'd like this to work like the methods that use <code>CanBuildFrom</code> and always keep the original type if possible. Is there a way? Or do Map subclasses always have to leave the value type as a type parameter?</p>
  
  <p>Here's a complete compilable example:</p>
  
  <pre><code>import scala.collection.immutable
  
  // pointless class that wraps another map and adds one method
  class FixedMap(val impl : Map[String, Int])
      extends immutable.Map[String, Int] with immutable.MapLike[String, Int, FixedMap] {
  
      override val empty : FixedMap = FixedMap.empty
  
      // This should return FixedMap if B1 is Int, and Map[String,B1]
      // if B1 is a superclass of Int; but there's no way to do that.
      // It is possible to return FixedMap here but then you have to
      // throw at runtime if B1 is not Int
      override def +[B1 &gt;: Int](kv : (String, B1)) : Map[String, B1] = {
          kv match {
              case (k, v : Int) =&gt;
                  new FixedMap(impl + Pair(k, v))
              case _ =&gt;
                  impl + kv
          }
      }
  
      override def -(key : String) : FixedMap = {
          new FixedMap(impl - key)
      }
  
      override def get(key : String) : Option[Int] = {
          impl.get(key)
      }
  
      override def iterator : Iterator[(String, Int)] = {
          impl.iterator
      }
  
      def somethingOnlyPossibleOnFixedMap() = {
          println("FixedMap says hi")
      }
  }
  
  object FixedMap {
      val empty : FixedMap = new FixedMap(Map.empty)
  }
  
  object TestIt {
      val empty = FixedMap.empty
      empty.somethingOnlyPossibleOnFixedMap()
      val one = empty + Pair("a", 1)
      // Can't do the below because one is a Map[String,Int] not a FixedMap
      // one.somethingOnlyPossibleOnFixedMap()
  }
  </code></pre>