Skip to content

Instantly share code, notes, and snippets.

@sgrankin
Created July 14, 2017 15:24
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save sgrankin/97721f7371e31c5803a308ba2e327cc2 to your computer and use it in GitHub Desktop.
Save sgrankin/97721f7371e31c5803a308ba2e327cc2 to your computer and use it in GitHub Desktop.
scala tagged types
import com.twitter.bijection.Bijection
package object tagging {
sealed trait Tagged[+V, +T]
type @@[+V, +T] = V with Tagged[V, T]
object Tagged {
implicit class Untaggable[V, T](val tagged: V @@ T) extends AnyVal {
@inline def untag: V = tagged
}
implicit class UntaggableM[M[+_], V, T](val tagged: M[V @@ T]) extends AnyVal {
@inline def untagM: M[V] = tagged
}
}
implicit class Taggable[V](val value: V) extends AnyVal {
@inline def tag[T] = value.asInstanceOf[V @@ T]
@inline def tagAs[T <: V @@ _] = value.asInstanceOf[T]
}
implicit class TaggableM[M[_], V](val value: M[V]) extends AnyVal {
@inline def tagM[T] = value.asInstanceOf[M[V @@ T]]
@inline def tagAsM[T <: V @@ _] = value.asInstanceOf[M[T]]
}
}
object test {
import tagging._
trait Foo
trait Bar
type Z = Int @@ Foo
val z: Z = 3.tagAs[Z]
val t: Long = 42L
val t2: @@[Long, Foo] = 42L.tag[Foo]
val x: @@[Long, Foo] = t2
val x2: @@[Long, Foo] = 2L.tag
val y: Long = x.untag
val y2: @@[Long, Bar] = x.untag.tag[Bar]
val c = Seq(1, 2, 3).tagM[Foo]
val d = c.untagM
}
object bijectionTest {
import com.twitter.bijection.Conversion.asMethod
trait Foo
import tagging._
implicit object xConv extends Bijection[Long, Long @@ Foo] {
override def apply(a: Long): @@[Long, Foo] = a.tag
override def invert(b: @@[Long, Foo]): Long = b.untag
}
val x = 42L.as[Long @@ Foo]
val y = x.as[Long]
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment