Created
June 6, 2012 04:55
-
-
Save jliszka/2880013 to your computer and use it in GitHub Desktop.
Multiple phantom types in a single type parameter
This file contains hidden or 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
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