Are there any plans to start supporting union types, similarly to how it’s done in Dotty (e.g.,
Int | Long | Float | Double)? If yes, is there any time estimate?
If not, what would be the best way to implement the following functionality in Scala 2.12?
Suppose we are interacting with a native C++ library supporting both Float32 (i.e.,
Float) and Float64 (i.e.,
Double) data types. We want to define a
DataType trait in our library, subclassed by
DataType.Float64 that implement functionality such as casting for example. In that trait we want to have an abstract type
T, which the
DataType.Float32 will override with value
DataType.Float64 will override with value
Double. In that trait we also define a couple methods:
def cast[V <: Float | Double](value: V): T def setElementInBuffer(buffer: ByteBuffer, index: Int, value: T): Unit def getElementFromBuffer(buffer: ByteBuffer, index: Int): T
T here can only be either
Double, but the compiler does not know that. Let’s say we read from one buffer of some data type, cast the elements, and write in a buffer of the other data type. Ideally we want cast to be specialized for the primitives. For type
V, above, the constraint can be enforced by something like the solution of Miles Sabin.
However, currently there is no way to make the compiler aware that
T can only be
Double. We could use a witness-style inheritance-based pattern, but that would force boxing of the primitive values and thus be inefficient. Defining type
T <: Float | Double (like in Dotty) would be ideal. Is there a way to mimic that behavior currently in Scala, without boxing the primitives?
Note that paraneterizing the DataType trait with
T and having a context bound there does not work. The reason is this: suppose a class Tensor has a data type but holds a reference to a C++ Tensor with an integer representing its data type. Then the way we obtain the data type is by calling a JNI function that returns that integer which we then convert to a
DataType[_]. This makes the compiler unable to verify that one tensors data type returns elements that can be fed into another tensor’s buffer (after casting to the appropriate type).
I hope this application description is sufficient for understanding the problem, but I can provide more details if necessary.