Skip to content

Instantly share code, notes, and snippets.

@octonato
Last active August 29, 2015 14:10
Show Gist options
  • Save octonato/15f013293ab4a7cd11f2 to your computer and use it in GitHub Desktop.
Save octonato/15f013293ab4a7cd11f2 to your computer and use it in GitHub Desktop.
Tagger / Untagger
/*
Based on @milessabin's https://gist.github.com/milessabin/89c9b47a91017973a35f
Note the swap: T for Tag and U for Untagged type
*/
type Tag[U, T] = {
type Tag = T
type Untagged = U
}
type @@[U, T] = U with Tag[U, T]
implicit class Tagger[U](untagged: U) {
def tagged[T]: U @@ T = untagged.asInstanceOf[U @@ T]
}
implicit class Untagger[U, T](tagged: @@[U,T]) {
def untag : U = tagged
}
trait New
trait Persisted
case class Foo(name:String)
val foo = Foo("abc")
val taggedFoo = foo.tagged[New]
// taggedFoo: @@[Foo,New] = Foo(abc)
val untaggedFoo = taggedFoo.untag
// untaggedFoo: this.Untagged = Foo(abc)
val untaggedFooOneLiner = foo.tagged[Persisted].untag
// untaggedFooOneLiner: Foo = Foo(abc)
/*
When type Untagged is commented out, it's impossible to untag, although type U is known
*/
type Tag[U, T] = {
type Tag = T
// type Untagged = U
}
type @@[U, T] = U with Tag[U, T]
implicit class Tagger[U](untagged: U) {
def tagged[T]: U @@ T = untagged.asInstanceOf[U @@ T]
}
implicit class Untagger[U, T](tagged: @@[U,T]) {
def untag : U = tagged
}
trait New
trait Persisted
case class Foo(name:String)
val foo = Foo("abc")
val taggedFoo = foo.tagged[New]
// taggedFoo: @@[Foo,New] = Foo(abc)
val untaggedFoo = taggedFoo.untag
//untaggedFoo: @@[Foo,New] = Foo(abc)
val untaggedFooOneLiner = foo.tagged[Persisted].untag
// untaggedFooOneLiner: Foo = Foo(abc)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment