Skip to content

Instantly share code, notes, and snippets.

@etorreborre
Created October 11, 2012 03:54
Show Gist options
  • Save etorreborre/3870064 to your computer and use it in GitHub Desktop.
Save etorreborre/3870064 to your computer and use it in GitHub Desktop.
Unboxed union types with a context bound
/**
* 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