-
-
Save milessabin/89c9b47a91017973a35f to your computer and use it in GitHub Desktop.
// Compile with -optimize to eliminate boxing/unboxing in specialized | |
// tag methods. | |
class User | |
class Checkin | |
type Tagged[U] = { type Tag = U } | |
type @@[T, U] = T with Tagged[U] // Thanks to @retronym for suggesting this type alias | |
class Tagger[U] { | |
def apply[T](t : T) : T @@ U = t.asInstanceOf[T @@ U] | |
} | |
def tag[U] = new Tagger[U] | |
// Manual specialization needed here ... specializing apply above doesn't help | |
def tag[U](i : Int) : Int @@ U = i.asInstanceOf[Int @@ U] | |
def tag[U](l : Long) : Long @@ U = l.asInstanceOf[Long @@ U] | |
def tag[U](d : Double) : Double @@ U = d.asInstanceOf[Double @@ U] | |
def fetch[A](id: Int @@ A): A = null.asInstanceOf[A] | |
def main(args: Array[String]): Unit = { | |
val id = tag[Checkin](10) | |
fetch[Checkin](id) // Compiles | |
fetch[User](id) // Does not compile | |
val ids = tag[User](1) :: tag[User](2) :: tag[User](3) :: Nil | |
val users : List[(Int @@ User)] = ids // Compiles | |
val checkins : List[Int @@ Checkin] = ids // Does not compile | |
} |
With a few type aliases for good measure: https://gist.github.com/8fe2c19e4431e817015b
@retronym Yup, I like the look of those.
Brilliant. I'm just researching how units of measurements can be implemented in Scala. Would it be possible to make this also support unit conversions, e. g. Length * Time == Speed and comparable things?
@soc No I don't think it's up to that. The main problem is that eg. Int @@ T <: Int for any T, so the usual arithmetic operators are applicable (via simple subtype conformance of their arguments) and will have their ordinary result type (ie. Int). So, in particular, tagUser+tagCheckin compiles and has the value 36 : Int ... definitely not what you want for UoM.
I need type tagging only (without shapeless or scalaz) in some projects so I published it as a one-class artifact, if anybody would find that useful as well: https://github.com/softwaremill/scala-common
It's not useful.