Created
January 19, 2014 18:35
-
-
Save OlegIlyenko/8508980 to your computer and use it in GitHub Desktop.
Advanced Type Constraints with Type Classes.
This file contains 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
import scala.reflect.runtime.universe.TypeTag | |
import scala.annotation.implicitNotFound | |
@implicitNotFound("Sorry, type inference was unable to figure out the type. You need to provide it explicitly.") | |
trait NotNothing[T] | |
object NotNothing { | |
private val evidence: NotNothing[Any] = new Object with NotNothing[Any] | |
implicit def notNothingEvidence[T](implicit n: T =:= T): NotNothing[T] = | |
evidence.asInstanceOf[NotNothing[T]] | |
} | |
def inject[T](implicit tt: TypeTag[T], nn: NotNothing[T]) = | |
tt.toString | |
inject | |
// <console>:12: error: Sorry, type inference was unable to figure out the type. You need to provide it explicitly. | |
// inject | |
// ^ | |
inject[Nothing] | |
// <console>:12: error: Sorry, type inference was unable to figure out the type. You need to provide it explicitly. | |
// inject[Nothing] | |
// ^ | |
val foo: String = inject | |
// <console>:11: error: Sorry, type inference was unable to figure out the type. You need to provide it explicitly. | |
// val foo: String = inject | |
// ^ | |
inject[String] | |
// res6: String = TypeTag[String] | |
inject[Int] | |
// res7: String = TypeTag[Int] |
This file contains 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
def inject[T](implicit tt: TypeTag[T], nn: Not[T =:= Nothing]) = | |
tt.toString | |
inject | |
// <console>:11: error: Argument does not satisfy constraints: Not =:=[T,Nothing] | |
// inject | |
// ^ | |
inject[Nothing] | |
// <console>:11: error: Argument does not satisfy constraints: Not =:=[Nothing,Nothing] | |
// inject[Nothing] | |
// ^ | |
val foo: String = inject | |
// <console>:10: error: Argument does not satisfy constraints: Not =:=[T,Nothing] | |
// val foo: String = inject | |
// ^ | |
inject[String] | |
// res3: String = TypeTag[String] | |
inject[Int] | |
// res4: String = TypeTag[Int] | |
def union1[T](t: T)(implicit c: (T =:= String) Or (T =:= Int)) = t match { | |
case s: String => println(s"Some nice string: $s") | |
case i: Int => println(s"Some int: $i") | |
} | |
type V[A, B] = {type l[T] = (T <:< A) Or (T <:< B)} | |
def union[T: (String V Int)#l](t: T) = t match { | |
case s: String => println(s"Some nice string: $s") | |
case i: Int => println(s"Some int: $i") | |
} | |
union("Test") | |
// Some nice string: Test | |
union(265) | |
// Some int: 265 | |
union(2.0) | |
// <console>:11: error: Argument does not satisfy constraints: =:=[Double,String] Or =:=[Double,Int] | |
// union(2.0) | |
// ^ | |
def sort[T: Ordering](list: List[T])(implicit c: Not[(T =:= String) Or Numeric[T]]) = | |
list.sorted | |
sealed trait Color | |
case object Red extends Color | |
case object Green extends Color | |
case object Blue extends Color | |
case object Yellow extends Color | |
case object Magenta extends Color | |
def printColor1[T](t: T)(implicit c: (T =:= Red.type) Or (T =:= Green.type) Or (T =:= Magenta.type)) = | |
println(t) | |
def printColor[T](t: T)(implicit c: (T <:< Color) And Not[T =:= Color] And Not[(T =:= Yellow.type) Or (T =:= Blue.type)]) = | |
println(t) | |
printColor(Yellow) | |
// <console>:11: error: Argument does not satisfy constraints: And[<:<[Yellow.type,Color],Not[=:=[Yellow.type,Color]]] And Not[Or[=:=[Yellow.type,Yellow.type],=:=[Yellow.type,Blue.type]]] | |
// printColor(Yellow) | |
// ^ | |
val c: Color = Magenta | |
// c: Color = Magenta | |
printColor(c) | |
// <console>:12: error: Argument does not satisfy constraints: And[<:<[Color,Color],Not[=:=[Color,Color]]] And Not[Or[=:=[Color,Yellow.type],=:=[Color,Blue.type]]] | |
// printColor(c) | |
// ^ | |
printColor(Magenta) | |
// Magenta |
This file contains 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
import scala.annotation.implicitNotFound | |
sealed trait Existence | |
trait Exists extends Existence | |
trait NotExists extends Existence | |
trait IsTypeClassExists[TypeClass, Answer] | |
object IsTypeClassExists { | |
private val evidence: IsTypeClassExists[Any, Any] = | |
new Object with IsTypeClassExists[Any, Any] | |
implicit def typeClassExistsEv[TypeClass, Answer](implicit a: TypeClass) = | |
evidence.asInstanceOf[IsTypeClassExists[TypeClass, Exists]] | |
implicit def typeClassNotExistsEv[TypeClass, Answer] = | |
evidence.asInstanceOf[IsTypeClassExists[TypeClass, NotExists]] | |
} | |
@implicitNotFound("Argument does not satisfy constraints: Not ${T}") | |
trait Not[T] | |
object Not { | |
private val evidence: Not[Any] = new Object with Not[Any] | |
implicit def notEv[T, Answer](implicit a: IsTypeClassExists[T, Answer], ne: Answer =:= NotExists) = | |
evidence.asInstanceOf[Not[T]] | |
} | |
@implicitNotFound("Argument does not satisfy constraints: ${A} And ${B}") | |
trait And[A, B] | |
object And { | |
private val evidence: And[Any, Any] = new Object with And[Any, Any] | |
implicit def bothExistEv[A, B](implicit a: A, b: B) = | |
evidence.asInstanceOf[And[A, B]] | |
} | |
@implicitNotFound("Argument does not satisfy constraints: ${A} Or ${B}") | |
trait Or[A, B] | |
object Or { | |
private val evidence: Or[Any, Any] = new Object with Or[Any, Any] | |
implicit def aExistsEv[A, B](implicit a: A) = | |
evidence.asInstanceOf[Or[A, B]] | |
implicit def bExistsEv[A, B](implicit b: B) = | |
evidence.asInstanceOf[Or[A, B]] | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
You can find more information here: http://hacking-scala.org/post/73854628325/advanced-type-constraints-with-type-classes