This will work
def get(size: Int)(implicit tag: ClassTag[DataType]) = new Array[DataType](size)
Or using an equivalent context bound
def get[DType: ClassTag](size: Int) = new Array[DType](size)
you could even replace DType with a template T.
Array's constructor actually takes an implicit parameter of type ClassTag and therefore you need to supply one, either implicitly or explicitly.
EDIT: Also worth noting that using dtype.DType will not work because dtype is of type DataType that has no concrete DType but only an abstract one. Funnily enough dtype.type will work just fine because at runtime val dtype: DataType is already an IntType.
EDIT2: If you want to propagate the type, I am afraid that the only way would be to use type classes.
import scala.reflect.ClassTag
object Types {
trait DataType[A] {
// more stuff
}
object IntType extends DataType[Int]
object StringType extends DataType[String]
trait Codec[B] {
val dtype: DataType[B]
// more stuff
}
class DenseCodec[B](val dtype: DataType[B]) extends Codec[B] {
def get(size: Int)(implicit ct: ClassTag[B]) = new Array[B](size)
}
def main(args: Array[String]): Unit = {
val denseInt = new DenseCodec(IntType)
val arrInt = denseInt.get(4) //Array[Int]
val denseString = new DenseCodec(StringType)
val arrString = denseString.get(4) //Array[String]
}
}
This way you can get rid of the DType and use the type class's type instead. You don't introduce any boilerplate because you wanted to define IntType and probably more types anyway.
Hope this one solves your problem :)
EDIT3: If you want to keep your DType just go with
trait DataType[A] {
type DType = A
// more stuff
}
and modify get definition
def get(size: Int)(implicit ct: ClassTag[B]) = new Array[dtype.DType](size)
But this way you will have a long type signature derived from IntType, StringType etc..