Idea for a Scala macro to make working with tagged types more ergonomic.
As a user, I want to define two variables:
$TYPE
: The name of the new type that we are creating.$CONTENT
: The actual, underlying content of the new type.
This will define a new type called $TYPE
that is a transparent, no-overhead wrapper around a value of type $CONTENT
.
After supplying these values, I want to automatically produce the the following code:
import scalaz.@@
type $TYPE = $TYPE.Content @@ $TYPE.Phantom
object $TYPE {
def apply(x: Content): $TYPE = Tag[Content, Phantom](x)
def apply(x: $TYPE): Content = Tag.unwrap[Content, Phantom](x)
sealed trait Phantom
type Content = $CONTENT
}
Substituting $CONTENT and $TYPE for the actual, user-defined values.
This above code means that if we have a value named x
of type $CONTENT
, then we can transpartently, easily convert it to and fro.
Suppose we want to convert x
to an instance of $TYPE
. We can do so with the method $TYPE.apply
: we can say $TYPE(x)
to do this.
Let's say we have a value named y
in the context val y = $TYPE(x)
. We can convert y
to the actual content type with the same syntax: $TYPE(y)
.
Maybe use the macro as:
@tagged type $TYPE = newtype[$CONTENT]
Right now, to have a newtype called Average
(a floating point average), I'd need to write:
import scalaz.@@
type Average = Average.Content @@ Average.Phantom
object Average {
def apply(x: Content): Average = Tag[Content, Phantom](x)
def apply(x: Average): Content = Tag.unwrap[Content, Phantom](x)
sealed trait Phantom
type Content = Double
}
This is boilerplate-y :(. Instead, I'd like to be able to do something similiar to:
@tagged type Average = newtype[Double]
Investigate:
- How to make such a macro?
- Generating the code from the 2 inputs.
- Scala snytax for invoking such a macro.
- Using an annotation? A method value?
Tagged types:
http://eed3si9n.com/learning-scalaz/Tagged+type.html