Skip to content

Instantly share code, notes, and snippets.

@rudogma
Last active May 24, 2017 06:59
Show Gist options
  • Save rudogma/b478024c50404406571e0aab90a57655 to your computer and use it in GitHub Desktop.
Save rudogma/b478024c50404406571e0aab90a57655 to your computer and use it in GitHub Desktop.
Tagging & Multitagging
import scala.language.higherKinds
object tag3 {
private def cast[T, U](v:U):T = v.asInstanceOf[T]
type Tag[T, +U] = { type Raw = T ; type Gag <: U }
type @@[T, +U] = T with Tag[T, U]
type Tagged[T, +U] = T with Tag[T, U]
trait TaggedType[T] {
sealed trait Tag
type Raw = T
type Type = T @@ Tag
def apply[K >: T](raw: K): T @@ Tag = cast(raw) //raw @@ Tag
}
implicit class TaggedVersion1[T](val value: T) extends AnyVal {
def @@(typ: TaggedType[T]): T @@ typ.Tag = cast(value)
}
implicit class TaggedVersion2[T, U](val value: Tag[T, U]) extends AnyVal {
def @@(typ: TaggedType[T]): T @@ (U with typ.Tag) = cast(value)
}
sealed trait ExceptF[F[_]]
implicit def allowAnyF[F[_]]:ExceptF[F] = new ExceptF[F] {}
implicit def disableComparableF:ExceptF[Comparable] = new ExceptF[Comparable] {}
implicit class TaggedVersion3[F[_] : ExceptF, T](val value: F[T]) {
def @@(typ: TaggedType[T]): F[T @@ typ.Tag] = cast(value)
}
implicit class TaggedVersion4[T, U, F[_]](val value: F[Tag[T,U]]) {
def @@@(typ: TaggedType[T]): F[T @@ (U with typ.Tag)] = cast(value)
}
}
import tag3._
import scala.reflect.runtime.universe.reify
object TestTags2 extends App {
System.setProperty("scala.time","true")
object User extends TaggedType[String]
type User = User.Type
object User2 extends TaggedType[String]
type User2 = User2.Type
object User3 extends TaggedType[String]
type User3 = User3.Type
def checkString(user:String):Unit = {
println(s"userString: $user, char(0)=${user.charAt(0)}")
}
def checkU(user:User): Unit ={
println(s"user: ${user}, char(0)=${user.charAt(0)}")
}
def checkU2(user:User2): Unit ={
println(s"user2: ${user}, char(0)=${user.charAt(0)}")
}
def checkU3(user:User3): Unit = {
println(s"user3: ${user}, char(0)=${user.charAt(0)}")
}
val user = "Hodor" @@ User //@@@ User3
println( reify(user))
println(s"user0: ${user}, len: ${user.length}")
println("--plain object.apply")
val u0 = User("rqweq")
checkString(u0)
checkU(u0)
println("--user && multi tags")
val u1 = "Hodor" @@ User
checkU(user)
println(reify(u1))
println(reify(new TaggedVersion2(u1)))
println("---u2")
val u2 = u1 @@ User2
checkU(u2)
checkU2(u2)
println("---dddd")
println("u2: "+u2)
println("-----u3")
val u3 = u2 @@ User3
checkString(u3)
checkU(u3)
checkU2(u3)
checkU3(u3)
println("----u1+u2+u3-oneliner")
val u4 = "Goga" @@ User @@ User2 @@ User3
println(reify(u4))
checkU(u3)
checkU2(u3)
checkU3(u3)
println("---list")
val rawUsers = List("scooper", "lhofstadter", "rkoothrappali")
val users = rawUsers @@ User
println(reify(users))
users.foreach( checkU )
println("---list users2")
val users2 = new TaggedVersion4[String, User.Tag, List](users) @@@ User2
println(reify(users2))
users2.foreach( checkU )
users2.foreach( checkU2 )
//fails to refine correct type bounds for implicit class
// println("---list[string with user.tag with user2.tag]")
// val user3 = rawUsers @@ User @@@ User2
println(System.currentTimeMillis())
}
Expr[io.treeve.tag3.@@[java.lang.String,io.treeve.TestTags2.User.Tag]](TestTags2.this.user)
user0: Hodor, len: 5
--plain object.apply
userString: rqweq, char(0)=r
user: rqweq, char(0)=r
--user && multi tags
user: Hodor, char(0)=H
Expr[io.treeve.tag3.@@[java.lang.String,io.treeve.TestTags2.User.Tag]](TestTags2.this.u1)
Expr[io.treeve.tag3.TaggedVersion2[io.treeve.TestTags2.u1.Raw,io.treeve.TestTags2.u1.Gag]](new tag3.TaggedVersion2(TestTags2.this.u1))
---u2
user: Hodor, char(0)=H
user2: Hodor, char(0)=H
---dddd
u2: Hodor
-----u3
userString: Hodor, char(0)=H
user: Hodor, char(0)=H
user2: Hodor, char(0)=H
user3: Hodor, char(0)=H
----u1+u2+u3-oneliner
Expr[io.treeve.tag3.@@[<refinement>.this.Raw,<refinement>.this.Gag with io.treeve.TestTags2.User3.Tag]](TestTags2.this.u4)
user: Hodor, char(0)=H
user2: Hodor, char(0)=H
user3: Hodor, char(0)=H
---list
Expr[List[io.treeve.tag3.@@[java.lang.String,io.treeve.TestTags2.User.Tag]]](TestTags2.this.users)
user: scooper, char(0)=s
user: lhofstadter, char(0)=l
user: rkoothrappali, char(0)=r
---list users2
Expr[scala.List[io.treeve.tag3.@@[String,io.treeve.TestTags2.User.Tag with io.treeve.TestTags2.User2.Tag]]](TestTags2.this.users2)
user: scooper, char(0)=s
user: lhofstadter, char(0)=l
user: rkoothrappali, char(0)=r
user2: scooper, char(0)=s
user2: lhofstadter, char(0)=l
user2: rkoothrappali, char(0)=r
1495609044246
[total 50ms]
[success] Total time: 2 s, completed 24.05.2017 9:57:24
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment