Skip to content
Create a gist now

Instantly share code, notes, and snippets.

Embed URL


Subversion checkout URL

You can clone with
Download ZIP
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 :(

And duly, Mark Harrah has shown me up with some type level fancy-pants:


Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.