Skip to content

Instantly share code, notes, and snippets.

@milessabin
Created September 21, 2011 17:04
Show Gist options
  • Star 54 You must be signed in to star a gist
  • Fork 13 You must be signed in to fork a gist
  • Save milessabin/89c9b47a91017973a35f to your computer and use it in GitHub Desktop.
Save milessabin/89c9b47a91017973a35f to your computer and use it in GitHub Desktop.
Unboxed newtype in Scala?
// 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
}
@milessabin
Copy link
Author

@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.

@adamw
Copy link

adamw commented Nov 25, 2015

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

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment