Created
October 11, 2012 03:54
-
-
Save etorreborre/3870064 to your computer and use it in GitHub Desktop.
Unboxed union types with a context bound
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
/** | |
* this is an experiment to create unboxed union types with a phantom type and a context bound. | |
* All the good ideas come from @milessabin post, comments and links: http://www.chuusai.com/2011/06/09/scala-union-types-curry-howard/#comment-22 | |
*/ | |
/** trait for anything that can be A or B */ | |
trait Or[A, B] { | |
// a phantom type, there will be no instance of this type that we'll use | |
type l[T] | |
// an alias for l[t] | |
type anyOf[T] = l[T] | |
} | |
// implicit definitions for various combinations of (A Or B)[T], (A Or B Or C)[T], (A Or B Or C Or D)[T] | |
implicit def OrInstance[A, B]: Or[A, B]#l[A] = | |
null.asInstanceOf[Or[A, B]#l[A]] | |
implicit def OrInstance2[A, B]: Or[A, B]#l[B] = | |
null.asInstanceOf[Or[A, B]#l[B]] | |
implicit def OrInstance3[A, B, C]: Or[Or[A, B], C]#l[A] = | |
null.asInstanceOf[Or[Or[A, B], C]#l[A]] | |
implicit def OrInstance4[A, B, C]: Or[Or[A, B], C]#l[B] = | |
null.asInstanceOf[Or[Or[A, B], C]#l[B]] | |
implicit def OrInstance5[A, B, C]: Or[Or[A, B], C]#l[C] = | |
null.asInstanceOf[Or[Or[A, B], C]#l[C]] | |
implicit def OrInstance6[A, B, C, D]: Or[Or[Or[A, B], C], D]#l[A] = | |
null.asInstanceOf[Or[Or[Or[A, B], C], D]#l[A]] | |
implicit def OrInstance7[A, B, C, D]: Or[Or[Or[A, B], C], D]#l[B] = | |
null.asInstanceOf[Or[Or[Or[A, B], C], D]#l[B]] | |
implicit def OrInstance8[A, B, C, D]: Or[Or[Or[A, B], C], D]#l[C] = | |
null.asInstanceOf[Or[Or[Or[A, B], C], D]#l[C]] | |
implicit def OrInstance9[A, B, C, D]: Or[Or[Or[A, B], C], D]#l[D] = | |
null.asInstanceOf[Or[Or[Or[A, B], C], D]#l[D]] | |
// a type alias to play with a different syntax | |
type /[A, B] = Or[A, B] | |
case class A() | |
/** | |
* a size method which only accepts Int or String or A or Double | |
*/ | |
def size[T : (Int / String / A / Double)#anyOf](t: T) = t match { | |
case i: Int => i | |
case d: Double => d.toInt | |
case s: String => s.length | |
case other => other.toString.length | |
} | |
size(3) | |
size("1234") | |
size(A()) | |
size(5.0) | |
// compile-error here because no implicit definition can be found | |
size(1f) |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment