Search code examples
scalainner-classespath-dependent-type

Scala: Assigning path dependant type to type projection


he following compiles:

import scala.collection.mutable.MutableList

abstract class GeomBase[T <: DTypes]
{  
  val grids = new MutableList[GridBase]

  def hexs: MutableList[GridBase#HexG with T#HexTr] = grids.flatMap(_.hexs.toList)
  //the above compiles fine

  abstract class GridBase
  { 
    val hexs: MutableList[HexG with T#HexTr] = new MutableList[HexG with T#HexTr]


    class HexG(coodI: Cood) extends Hex
    {
    }
  }
}

But when I change the line from this

def hexs: MutableList[GridBase#HexG with T#HexTr] = grids.flatMap (_.hexs.toList)

to this (changing the MutableList into a List)

def hexs: List[GridBase#HexG with T#HexTr] = grids.flatMap (_.hexs.toList)

it doesn't compile any more. This doesn't compile either

def hexs: MutableList[GridBase#HexG with T#HexTr] = grids(0).hexs

It wont compile, saying I need a MutableList in the former case and type incompatibility in the latter. I don't understand why. Just to clarify in case its causing confusion HexG is an inner class of GridBase which is itself an inner class of GeomBase.

Update: Travis Brown's answer seems to provide the correct explanation for the first error. I've changed all the uses of MutableList to List. Surprisingly this not only stopped the first error but also the second. I also got errors when trying to use the types outside of the outermost GeomBase class. I got a compiler crash. when instantiating the type. Changing to Lists from MutableLists again unexpectedly removed one of these errors but not the compiler crash. I had been using Scala Eclipse plugin 2.1 special edition for 2.10.0-M3. This leads me to the conclusion that there still may be problems with the Scala compiler and path dependant types.


Solution

  • The problem here (probably) doesn't have anything to do with the path-dependent types. Consider the following:

    val xs: MutableList[Seq[Int]] = new MutableList ++ Seq(1 to 2, 3 to 4)
    

    Now we can do the following, for example:

    scala> xs.flatMap(_.toList)
    res0: scala.collection.mutable.MutableList[Int] = MutableList(1, 2, 3, 4)
    

    But a MutableList isn't a List:

    scala> xs.flatMap(_.toList): List[Int]
    <console>:10: error: type mismatch;
     found   : scala.collection.mutable.MutableList[Int]
     required: List[Int]
                  xs.flatMap(_.toList): List[Int]
    

    If we'd called it a Seq[Int], for example, we'd be fine, since Seq is a supertype of MutableList. List isn't (despite the name).

    In your last example you're getting an error because grids(0).hexs doesn't have the right type—it's not a MutableList[GridBase#HexG with T#HexTr]. I'm not sure what it is, since you haven't shared that code with us.


    As a footnote: interestingly (or maybe not), the following does work:

    xs.flatMap(_.toList)(collection.breakOut): List[Int]
    

    Don't do this, though. breakOut is weird magic.