Skip to content

Instantly share code, notes, and snippets.

@retronym
Created July 15, 2010 15:28
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save retronym/477110 to your computer and use it in GitHub Desktop.
Save retronym/477110 to your computer and use it in GitHub Desktop.
Simulating a subtractive type with intentionally ambiguous implicits
trait Exclude[Scope, X]
object Exclude {
implicit def $$NOT_FOR_USER_CODE$$[X, A]: Exclude[X, A] = new Exclude[X, A] {}
def list[X] = new {
def apply[A] = $$NOT_FOR_USER_CODE$$[X, A]
}
}
sealed trait BoolOrInt
object BoolOrInt {
val exclude = Exclude.list[BoolOrInt]
implicit val b1, b2 = exclude[Boolean]
implicit val a1, a2 = exclude[Int]
}
def foo[T](t: T)(implicit n: Exclude[BoolOrInt, T]) = t
foo("") // works
foo(1) // fails!
foo(false) // fails!
foo(false)(Exclude.$$NOT_FOR_USER_CODE$$) // subverted :(
// Partially apply the type to be compatible with context bounds:
type Types[Scope] = {
type DoesNotContain[X] = Exclude[Scope, X]
}
def bar[T: Types[BoolOrInt]#DoesNotContain](t: T) = t
bar("") // works
bar(1) // fails!
bar(false) // fails!
bar(false)(Exclude.$$NOT_FOR_USER_CODE$$) // subverted :(
@retronym
Copy link
Author

And duly, Mark Harrah has shown me up with some type level fancy-pants: http://github.com/harrah/up/commit/aa00b48fd1e4e141235d305e5e877fb74f076f86

:)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment