Marker trait used to mark a type alias as being a distinct type alias (DTA).
Marker trait used to mark a type alias as being a distinct type alias (DTA). A DTA is an alternative to the Scala value-class (http://docs.scala-lang.org/overviews/core/value-classes.html) that never needs to box (or unbox) since type aliases are eliminated in byte code.
A DTA is always declared with a unique trait tag to make the type alias distinct in the type system. Since the DTA is a distinct type, type-classes of the DTA can be implicitly resolved. In Scala, a normal type alias would always resolve to its underlying type.
Tagging a type alias example: type Age1 = Int // implicitly[Format[Age] ] resolves to Format[Int] trait AgeTag type Age = Int with AgeTag // implicitly[Format[Age] ] is distinct from Format[Int]
Value-classes are elided by the compiler under many circumstances, but when used in any kind of generic, such as List or Option, they are emitted. To convert from a generic of the value-class type to the underlying type requires a no-op runtime call in byte code that may or may not be eliminated by downstream optimization. For collections such as List, this means a O(n) call to map simply to cast from the value-class to the underlying type. Because DTAs are simply type aliases for their underlying type the compiler can simply treat a generic of a DTA as a generic of the underlying type without any impact on runtime.
Converting the other direction for value-classes suffers from the same problem as stated above. Because DTAs require a distinct tag, the compiler can not automatically perform the downcast. Instead, implicit defs are created to support the operation as a casting operation that should be eliminated in otput byte code.
Example generic converter: implicit def ma_to_mv[M[_],V < : IsDistinctTypeAlias[A],A]( ma: M[A] ) : M[V] = ma.asInstanceOf[M[V] ]
A DTA is declared by first creating a trait tag that is used to make the DTA distinct. Next, the type alias is declared as a mix of the underlying type, the tag and the marker trait IsDistinctTypeAlias. The IsDistinctTypeAlias marker trait is used to in implicit def conversions that convert generics (such as collections) without overhead.
Full example: trait AgeTag type Age = Int with AgeTag with IsDistinctTypeAlias[Int] implicit def Age(i: Int) = i.asInstanceOf[Age]
A base trait for a user-defined value-class that standardizes the name of the value-class val to "underlying" and toString to underlying toString.
A base trait for a user-defined value-class that standardizes the name of the value-class val to "underlying" and toString to underlying toString. This allows creating an implicit conversion from an instance of any value-class to its underlying representation.
For details on value-class see: http://docs.scala-lang.org/overviews/core/value-classes.html
Example value-class: implicit class Name(underlying: String) extends AnyVal with IsValueType[String]
Note1: When using creating a value-class for String, it is necessary to create an implicit view to StringOps to use the Scala extended String methods on instances of the value-class. Example for Name above: object Name { import scala.collection.immutable.StringOps implicit def stringOps_Name(n: Name) = new StringOps(n.underlying) }
Note2: while almost every method on underlying can be used on the value-class without special code, the equals method is a special case that still requires wrapping the right-hand type in the value-class to match the other side. Ex:
Name("Hal") == "Hal" // always returns false + compiler warning Name("Hal") == Name("Hal") // works correctly
type of underlying value class (Note: this parameter does not require inheritance from AnyVal since this would prevent using the trait with java.lang.String which does not inherit AnyVal)
Implicitly convert any generic M[V] to M[A] where V is a distinct type alias of A
Implicitly convert any generic M[V] to M[A] where V is a distinct type alias of A
generic type
DTA type
underlying type of DTA
generic instance
instance cast to M[V]
Implicitly convert any generic M[A] to M[V] where V is a distinct type alias of A
Implicitly convert any generic M[A] to M[V] where V is a distinct type alias of A
generic type
DTA type
underlying type of DTA
generic instance
instance cast to M[V]
Implicitly convert any generic M[A,B] to a M[V,B] where V is a distinct type alias of A
Implicitly convert any generic M[A,B] to a M[V,B] where V is a distinct type alias of A
type of generic instance
underlying type of DTA
DTA type
some type
generic instance
instance cast to M[V,B]
Implicitly convert any generic M[A,B] to a M[A,V] where V is a distinct type alias of B
Implicitly convert any generic M[A,B] to a M[A,V] where V is a distinct type alias of B
type of generic instance
some type
DTA type
underlying type of DTA
generic instance
instance cast to M[A,V]
Implicitly convert a value class to its underlying type
Implicitly convert a value class to its underlying type
the underlying type
a value-class derived from IsValueClass
the wrapped value