Skip to content

Instantly share code, notes, and snippets.

@tixxit
Last active December 13, 2016 17:19
Show Gist options
  • Save tixxit/7fa642d5032747ed7b63c4b4b743662f to your computer and use it in GitHub Desktop.
Save tixxit/7fa642d5032747ed7b63c4b4b743662f to your computer and use it in GitHub Desktop.
package ambiguous
// A type class that can only be found if a corresponding type class `A` cannot be found.
final class Not[A]
object Not {
// Always available for any type.
implicit def not0[A]: Not[A] = new Not[A]
// If an implicit `A` also exists, then `Not` is ambiguous and compilation will fail.
implicit def not1[A](implicit a: A): Not[A] = new Not[A]
}
// A wrapper for some arbitrary value.
case class ForReals[A](value: A)
object ForReals {
// We always have an implicit conversion available for any `A`.
implicit def forRealsies[A](a: A): ForReals[A] = ForReals(a)
// However, if an `A` is only available via an implicit conversion from some other type,
// then we make an ambiguous implicit to force compilation to fail.
implicit def forRealsiesAmbig[A, B](a: A)(implicit ev: A => B, not: Not[A =:= B]): ForReals[B] = ???
}
final class TypedPipe[+A]
object TypedPipe {
implicit def vectorIsTypedPipe[A](vec: Vector[A]): TypedPipe[A] = new TypedPipe[A]
}
object MyThing {
implicit class UnitOps(unit: Unit) {
def foo[A](pipe: TypedPipe[A]) = pipe
def bar[A](pipe: ForReals[TypedPipe[A]]) = pipe
}
}
@tixxit
Copy link
Author

tixxit commented Dec 13, 2016

Example:

scala> import ambiguous._, MyThing._
import ambiguous._
import MyThing._

scala> ().foo(new TypedPipe[Int])
res0: ambiguous.TypedPipe[Int] = ambiguous.TypedPipe@4d010e0c

scala> ().bar(new TypedPipe[Int])
res1: ambiguous.ForReals[ambiguous.TypedPipe[Int]] = ForReals(ambiguous.TypedPipe@4cf51604)

scala> ().foo(Vector(1,2,3))
res2: ambiguous.TypedPipe[Int] = ambiguous.TypedPipe@47cb9cd6

scala> ().bar(Vector(1,2,3))
<console>:14: error: type mismatch;
 found   : scala.collection.immutable.Vector[Int]
 required: ambiguous.ForReals[ambiguous.TypedPipe[?]]
              ().bar(Vector(1,2,3))

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