Skip to content

Instantly share code, notes, and snippets.

@jliszka
Created June 6, 2012 04:55
Show Gist options
  • Star 3 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jliszka/2880013 to your computer and use it in GitHub Desktop.
Save jliszka/2880013 to your computer and use it in GitHub Desktop.
Multiple phantom types in a single type parameter
object test {
sealed trait Limited
sealed trait Unlimited
sealed trait Lim extends Limited with Unlimited
sealed trait Skipped
sealed trait Unskipped
sealed trait Sk extends Skipped with Unskipped
sealed trait Selected
sealed trait Unselected
sealed trait Sel extends Selected with Unselected
/**
* The availability of an implicit value of this type does 2 things:
* 1. asserts that In is a subclass of Unlimited, and
* 2. constrains Out to extend Limited instead of Unlimited
*/
class AddLimit[-In, +Out]
object AddLimit {
implicit def addLimit[Rest >: Sel with Sk]: AddLimit[Rest with Unlimited, Rest with Limited] = null
}
class AddSkip[-In, +Out]
object AddSkip {
implicit def addSkip[Rest >: Lim with Sel]: AddSkip[Rest with Unskipped, Rest with Skipped] = null
}
class AddSelect[-In, +Out]
object AddSelect {
implicit def addSelect[Rest >: Lim with Sk]: AddSelect[Rest with Unselected, Rest with Selected] = null
}
class Query[+T] {
def limit[T2](n: Int)(implicit ev: AddLimit[T, T2]): Query[T2] = this.asInstanceOf[Query[T2]]
def skip[T2](n: Int)(implicit ev: AddSkip[T, T2]): Query[T2] = this.asInstanceOf[Query[T2]]
def select[T2]()(implicit ev: AddSelect[T, T2]): Query[T2] = this.asInstanceOf[Query[T2]]
def fetch()(implicit ev: T <:< Limited): List[String] = Nil
}
}
import test._
val q = new Query[Unlimited with Unskipped with Unselected]
/*
scala> q.limit(3)
res0: Query[Unskipped with Unselected with Limited] = Query@578f7a8
scala> q.limit(3).select()
res1: Query[Limited with Unskipped with Selected] = Query@23218b01
scala> q.limit(3).limit(4)
<console>:23: error: could not find implicit value for parameter ev: Limit[Unskipped with Unselected with Limited,T2]
q.limit(3).limit(4)
^
scala> q.fetch()
<console>:23: error: could not find implicit value for parameter ev: Limit[_, Unlimited with Unskipped with Unselected]
q.fetch()
^
scala> q.limit(3).fetch()
res2: List[String] = List()
scala> val qq = if (true) q.limit(3) else q
qq: Query[Unskipped with Unselected] = Query@b12ce69
scala> qq.select()
res3: Query[Unskipped with Selected] = Query@b12ce69
*/
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment