Created
July 14, 2017 15:24
-
-
Save sgrankin/97721f7371e31c5803a308ba2e327cc2 to your computer and use it in GitHub Desktop.
scala tagged types
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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