Scala: Type mismatch, returns BlockList[Any] instead of BlockList[R]
Just to get more experience with Scala, and as an experiment, I'm
implementing a class that has a List-like API, but is implemented as a
list of IndexedSeq with an index to the first element; tail just returns a
copy with the index incremented, and prepending Arrays is O(1), while
appending Arrays is O(m), m = length of list <= number of elements.
I'm running into problems with my function return types. Pretty much every
method has the type parameters [R >: T : ClassManifest, A <: R :
ClassManifest], T being the type parameter of BlockList. Sometimes these
methods just return others, but in those situations I get an error from
Eclipse saying that it was looking for type BlockList[R] but found type
BlockList[Any]. Shouldn't R be the lowest common super type of both T and
A? In which case, the second method call should also return BlockList[R],
right? What am I not getting? I reflect ClassManifest a lot to overcome
the problems of type erasure, but I don't know if it's still a problem.
The errors are from the definitions of |: and :|. I also get an error from
new Build[R](block, next :| blk, index), saying that none of the
constructors can be applied to (IndexedSeq[T], BlockList[Any], Int).
import collection.immutable.List
import reflect.ClassManifest
import annotation.tailrec
sealed abstract
class BlockList [+T] extends Seq[T] with Product {
...
}
class Build [T: ClassManifest](
private val block: IndexedSeq[T],
private val next: BlockList[T] = EmptyBlock,
private val index: Int = 0
) extends BlockList[T] {
require(!block.isEmpty && index >= 0 && index < block.length)
def this (blk: Array[T], nxt: BlockList[T] = EmptyBlock, idx: Int = 0) {
this(blk toIndexedSeq, nxt, idx)
}
override def |: [R >: T : ClassManifest, A <: R] (x: A): BlockList[R] =
Array[R](x) |: this
override def |: [R >: T : ClassManifest, A <: R : ClassManifest]
(blk: IndexedSeq[A]): BlockList[R] =
if (blk isEmpty) this
else new Build[R](blk, this)
override def :| [R >: T : ClassManifest, A <: R] (x: A): BlockList[R] =
this :| Array[R](x)
override def :| [R >: T : ClassManifest, A <: R : ClassManifest]
(blk: IndexedSeq[A]): BlockList[R] =
if (blk isEmpty) this
else new Build[R](block, next :| blk, index)
override def :|: [R >: T : ClassManifest, A <: R : ClassManifest]
(prefix: BlockList[A]): BlockList[R] =
prefix match {
case prefix: Build[R] => prefix.block |: (prefix.next :|: this)
case EmptyBlock => this
}
override def apply (n: Int): T =
if (n < 0 || n >= length) throw new IndexOutOfBoundsException(
"Cannot get element "+n+"; not within bounds."
)
else if (n < block.length - index) block(n + index)
else next(n - block.length + index)
override lazy val length: Int = (block length) - index + (next length)
}
object EmptyBlock extends BlockList[Nothing] {
...
}
No comments:
Post a Comment