I know how @specialized
classes and value classes work and I know that I can't have a specialized value class as in:
class MilliVolt[@specialized T](val content :T) extends AnyVal //illegal
I can't find a way to obtain a similiar effect: with a single declaration create a user type/type constructor which can serve as a purely syntactic wrapper over several java primitives - is a workaround over this limitation possible?
One of primary motivations behind value classes was to 'annotate' value types with business meaning and creating a type different from the type of its data:
class MilliVolts(val count :Long) extends AnyVal
This works very well as long as you know statically the boxed type, but if you'd like to treat several different primitives as millivolts, you have an option of either creating a new wrapper for every primitive, or using generic for what they were designed to:
trait Scale
trait millivolts extends Scale
trait milliampere extends Scale
class of[N, U<:Scale](val amount :N) extends AnyVal
val voltage :Long of millivolts = new of(1L)
val current :Int of milliampere = new of(1)
This is all sweet and indeed of
wrapper is removed in compile time, but unfortunately primitives are boxed to their java wrappers, and the two fields
are compiled to:
Integer voltage = scala.Long.box(1L)
Integer current = scala.Int.box(1)
and not long
and int
fields.
Is it possible to write code that:
- allows to create new such wrappers with a single declaration (new 'unit' types);
- performs generic operations on such wrappers, at least in terms of the underlying primitive (methods operating on millivolts, abstracting from the boxed primitive);
- performs no boxing when both the wrapper type and underlying primitive type are fully instantiated (not type parameters of a generic type) and called method can be inlined (so I can define addition once for all current and future units)
- ideally doesn't rely on macros in client code (usage in implementation are fine, as long as type declaration itself is understandable by IDEs)