Created
May 15, 2012 21:59
-
-
Save DaveGit/2705479 to your computer and use it in GitHub Desktop.
Either with arity 5
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 language.implicitConversions | |
sealed abstract class Either5[+A, +B, +C, +D, +E] { | |
def _1 = c1.get | |
def _2 = c2.get | |
def _3 = c3.get | |
def _4 = c4.get | |
def _5 = c5.get | |
def c1 = Either5._1Projection(this) | |
def c2 = Either5._2Projection(this) | |
def c3 = Either5._3Projection(this) | |
def c4 = Either5._4Projection(this) | |
def c5 = Either5._5Projection(this) | |
def fold[X](fa: A => X, fb: B => X, fc: C => X, fd: D => X, fe: E => X) = this match { | |
case C1(a) => fa(a) | |
case C2(b) => fb(b) | |
case C3(c) => fc(c) | |
case C4(d) => fd(d) | |
case C5(e) => fe(e) | |
} | |
def rotateLeft = this match { | |
case C1(a) => C5(a) | |
case C2(b) => C1(b) | |
case C3(c) => C2(c) | |
case C4(d) => C3(d) | |
case C5(e) => C4(e) | |
} | |
def rotateRight = this match { | |
case C1(a) => C2(a) | |
case C2(b) => C3(b) | |
case C3(c) => C4(c) | |
case C4(d) => C5(d) | |
case C5(e) => C1(e) | |
} | |
def join_1[A1 >: A, B1 >: B, C1 >: C, D1 >: D, E1 >: E, F](implicit ev: A1 <:< Either5[F, B1, C1, D1, E1]): Either5[F, B1, C1, D1 , E1] = this match { | |
case C1(a) => a | |
case C2(b) => C2(b) | |
case C3(c) => C3(c) | |
case C4(d) => C4(d) | |
case C5(e) => C5(e) | |
} | |
def join_2[A1 >: A, B1 >: B, C1 >: C, D1 >: D, E1 >: E, F](implicit ev: B1 <:< Either5[A1, F, C1, D1, E1]): Either5[A1, F, C1, D1, E1] = this match { | |
case C1(a) => C1(a) | |
case C2(b) => b | |
case C3(c) => C3(c) | |
case C4(d) => C4(d) | |
case C5(e) => C5(e) | |
} | |
def join_3[A1 >: A, B1 >: B, C1 >: C, D1 >: D, E1 >: E, F](implicit ev: C1 <:< Either5[A1, B1, F, D1, E1]): Either5[A1, B1, F, D1, E1] = this match { | |
case C1(a) => C1(a) | |
case C2(b) => C2(b) | |
case C3(c) => c | |
case C4(d) => C4(d) | |
case C5(e) => C5(e) | |
} | |
def join_4[A1 >: A, B1 >: B, C1 >: C, D1 >: D, E1 >: E, F](implicit ev: D1 <:< Either5[A1, B1, C1, F, E1]): Either5[A1, B1, C1, F, E1] = this match { | |
case C1(a) => C1(a) | |
case C2(b) => C2(b) | |
case C3(c) => C3(c) | |
case C4(d) => d | |
case C5(e) => C5(e) | |
} | |
def join_5[A1 >: A, B1 >: B, C1 >: C, D1 >: D, E1 >: E, F](implicit ev: E1 <:< Either5[A1, B1, C1, D1, F]): Either5[A1, B1, C1, D1, F] = this match { | |
case C1(a) => C1(a) | |
case C2(b) => C2(b) | |
case C3(c) => C3(c) | |
case C4(d) => C4(d) | |
case C5(e) => e | |
} | |
def isC1: Boolean | |
def isC2: Boolean | |
def isC3: Boolean | |
def isC4: Boolean | |
def isC5: Boolean | |
} | |
final case class C1[+A, +B, +C, +D, +E](a: A) extends Either5[A, B, C, D, E] { | |
def isC1 = true | |
def isC2 = false | |
def isC3 = false | |
def isC4 = false | |
def isC5 = false | |
} | |
final case class C2[+A, +B, +C, +D, +E](b: B) extends Either5[A, B, C, D, E] { | |
def isC1 = false | |
def isC2 = true | |
def isC3 = false | |
def isC4 = false | |
def isC5 = false | |
} | |
final case class C3[+A, +B, +C, +D, +E](c: C) extends Either5[A, B, C, D, E] { | |
def isC1 = false | |
def isC2 = false | |
def isC3 = true | |
def isC4 = false | |
def isC5 = false | |
} | |
final case class C4[+A, +B, +C, +D, +E](d: D) extends Either5[A, B, C, D, E] { | |
def isC1 = false | |
def isC2 = false | |
def isC3 = false | |
def isC4 = true | |
def isC5 = false | |
} | |
final case class C5[+A, +B, +C, +D, +E](e: E) extends Either5[A, B, C, D, E] { | |
def isC1 = false | |
def isC2 = false | |
def isC3 = false | |
def isC4 = false | |
def isC5 = true | |
} | |
object Either5 { | |
class MergeableEither5[A](x: Either5[A, A, A, A, A]) { | |
def merge: A = x match { | |
case C1(a) => a | |
case C2(a) => a | |
case C3(a) => a | |
case C4(a) => a | |
case C5(a) => a | |
} | |
} | |
implicit def either2mergeable[A](x: Either5[A, A, A, A, A]): MergeableEither5[A] = new MergeableEither5(x) | |
final case class _1Projection[+A, +B, +C, +D, +E](e: Either5[A, B, C, D, E]) { | |
def get = e match { | |
case C1(a) => a | |
case C2(_) => throw new NoSuchElementException("Either._1.value on _2") | |
case C3(_) => throw new NoSuchElementException("Either._1.value on _3") | |
case C4(_) => throw new NoSuchElementException("Either._1.value on _4") | |
case C5(_) => throw new NoSuchElementException("Either._1.value on _5") | |
} | |
def foreach[U](f: A => U) = e match { | |
case C1(a) => f(a) | |
case C2(_) => {} | |
case C3(_) => {} | |
case C4(_) => {} | |
case C5(_) => {} | |
} | |
def getOrElse[AA >: A](or: => AA) = e match { | |
case C1(a) => a | |
case C2(_) => or | |
case C3(_) => or | |
case C4(_) => or | |
case C5(_) => or | |
} | |
def forall(f: A => Boolean) = e match { | |
case C1(a) => f(a) | |
case C2(_) => true | |
case C3(_) => true | |
case C4(_) => true | |
case C5(_) => true | |
} | |
def exists(f: A => Boolean) = e match { | |
case C1(a) => f(a) | |
case C2(_) => false | |
case C3(_) => false | |
case C4(_) => false | |
case C5(_) => false | |
} | |
def flatMap[BB >: B, CC >: C, DD >: D, EE >: E, X](f: A => Either5[X, BB, CC, DD, EE]) = e match { | |
case C1(a) => f(a) | |
case C2(b) => C2(b) | |
case C3(c) => C3(c) | |
case C4(d) => C4(d) | |
case C5(e) => C5(e) | |
} | |
def map[X](f: A => X) = e match { | |
case C1(a) => C1(f(a)) | |
case C2(b) => C2(b) | |
case C3(c) => C3(c) | |
case C4(d) => C4(d) | |
case C5(e) => C5(e) | |
} | |
def filter[X](p: A => Boolean): Option[Either5[A, X, X, X ,X]] = e match { | |
case C1(a) => if(p(a)) Some(C1(a)) else None | |
case C2(_) => None | |
case C3(_) => None | |
case C4(_) => None | |
case C5(_) => None | |
} | |
def toSeq = e match { | |
case C1(a) => Seq(a) | |
case C2(_) => Seq.empty | |
case C3(_) => Seq.empty | |
case C4(_) => Seq.empty | |
case C5(_) => Seq.empty | |
} | |
def toOption = e match { | |
case C1(a) => Some(a) | |
case C2(_) => None | |
case C3(_) => None | |
case C4(_) => None | |
case C5(_) => None | |
} | |
} | |
final case class _2Projection[+A, +B, +C, +D, +E](e: Either5[A, B, C, D, E]) { | |
def get = e match { | |
case C1(_) => throw new NoSuchElementException("Either._2.value on _1") | |
case C2(b) => b | |
case C3(_) => throw new NoSuchElementException("Either._2.value on _3") | |
case C4(_) => throw new NoSuchElementException("Either._2.value on _4") | |
case C5(_) => throw new NoSuchElementException("Either._2.value on _5") | |
} | |
def foreach[U](f: B => U) = e match { | |
case C1(_) => {} | |
case C2(b) => f(b) | |
case C3(_) => {} | |
case C4(_) => {} | |
case C5(_) => {} | |
} | |
def getOrElse[BB >: B](or: => BB) = e match { | |
case C1(_) => or | |
case C2(b) => b | |
case C3(c) => or | |
case C4(d) => or | |
case C5(e) => or | |
} | |
def forall(f: B => Boolean) = e match { | |
case C1(_) => true | |
case C2(b) => f(b) | |
case C3(_) => true | |
case C4(_) => true | |
case C5(_) => true | |
} | |
def exists(f: B => Boolean) = e match { | |
case C1(_) => false | |
case C2(b) => f(b) | |
case C3(_) => false | |
case C4(_) => false | |
case C5(_) => false | |
} | |
def flatMap[AA >: A, CC >: C, DD >: D, EE >: E, X](f: B => Either5[AA, X, CC, DD, EE]) = e match { | |
case C1(a) => C1(a) | |
case C2(b) => f(b) | |
case C3(c) => C3(c) | |
case C4(d) => C4(d) | |
case C5(e) => C5(e) | |
} | |
def map[Y](f: B => Y) = e match { | |
case C1(a) => C1(a) | |
case C2(b) => C2(f(b)) | |
case C3(c) => C3(c) | |
case C4(d) => C4(d) | |
case C5(e) => C5(e) | |
} | |
def filter[X](p: B => Boolean): Option[Either5[X, B, X, X, X]] = e match { | |
case C1(_) => None | |
case C2(b) => if(p(b)) Some(C2(b)) else None | |
case C3(_) => None | |
case C4(_) => None | |
case C5(_) => None | |
} | |
def toSeq = e match { | |
case C1(_) => Seq.empty | |
case C2(b) => Seq(b) | |
case C3(_) => Seq.empty | |
case C4(_) => Seq.empty | |
case C5(_) => Seq.empty | |
} | |
def toOption = e match { | |
case C1(_) => None | |
case C2(b) => Some(b) | |
case C3(_) => None | |
case C4(_) => None | |
case C5(_) => None | |
} | |
} | |
final case class _3Projection[+A, +B, +C, +D, +E](e: Either5[A, B, C, D, E]) { | |
def get = e match { | |
case C1(_) => throw new NoSuchElementException("Either._3.value on _1") | |
case C2(_) => throw new NoSuchElementException("Either._3.value on _2") | |
case C3(c) => c | |
case C4(_) => throw new NoSuchElementException("Either._3.value on _4") | |
case C5(_) => throw new NoSuchElementException("Either._3.value on _5") | |
} | |
def foreach[U](f: C => U) = e match { | |
case C1(_) => {} | |
case C2(_) => {} | |
case C3(c) => f(c) | |
case C4(_) => {} | |
case C5(_) => {} | |
} | |
def getOrElse[CC >: C](or: => CC) = e match { | |
case C1(_) => or | |
case C2(_) => or | |
case C3(c) => c | |
case C4(_) => or | |
case C5(_) => or | |
} | |
def forall(f: C => Boolean) = e match { | |
case C1(_) => true | |
case C2(_) => true | |
case C3(c) => f(c) | |
case C4(_) => true | |
case C5(_) => true | |
} | |
def exists(f: C => Boolean) = e match { | |
case C1(_) => false | |
case C2(_) => false | |
case C3(c) => f(c) | |
case C4(_) => false | |
case C5(_) => false | |
} | |
def flatMap[AA >: A, BB >:B, CC >:C, DD >:D, EE >:E, X](f: C => Either5[AA, BB, X, DD, EE]) = e match { | |
case C1(a) => C1(a) | |
case C2(b) => C2(b) | |
case C3(c) => f(c) | |
case C4(d) => C4(d) | |
case C5(e) => C5(e) | |
} | |
def map[X](f: C => X) = e match { | |
case C1(a) => C1(a) | |
case C2(b) => C2(b) | |
case C3(c) => C3(f(c)) | |
case C4(d) => C4(d) | |
case C5(e) => C5(e) | |
} | |
def filter[X](p: C => Boolean): Option[Either5[X, X, C, X, X]] = e match { | |
case C1(_) => None | |
case C2(_) => None | |
case C3(c) => if(p(c)) Some(C3(c)) else None | |
case C4(_) => None | |
case C5(_) => None | |
} | |
def toSeq = e match { | |
case C1(_) => Seq.empty | |
case C2(_) => Seq.empty | |
case C3(c) => Seq(c) | |
case C4(_) => Seq.empty | |
case C5(_) => Seq.empty | |
} | |
def toOption = e match { | |
case C1(_) => None | |
case C2(_) => None | |
case C3(c) => Some(c) | |
case C4(_) => None | |
case C5(_) => None | |
} | |
} | |
final case class _4Projection[+A, +B, +C, +D, +E](e: Either5[A, B, C, D, E]) { | |
def get = e match { | |
case C1(_) => throw new NoSuchElementException("Either._4.value on _1") | |
case C2(_) => throw new NoSuchElementException("Either._4.value on _2") | |
case C3(_) => throw new NoSuchElementException("Either._4.value on _3") | |
case C4(d) => d | |
case C5(_) => throw new NoSuchElementException("Either._4.value on _5") | |
} | |
def foreach[U](f: D => U) = e match { | |
case C1(_) => {} | |
case C2(_) => {} | |
case C3(_) => {} | |
case C4(d) => f(d) | |
case C5(_) => {} | |
} | |
def getOrElse[DD >: D](or: => DD) = e match { | |
case C1(_) => or | |
case C2(_) => or | |
case C3(_) => or | |
case C4(d) => d | |
case C5(_) => or | |
} | |
def forall(f: D => Boolean) = e match { | |
case C1(_) => true | |
case C2(_) => true | |
case C3(_) => true | |
case C4(d) => f(d) | |
case C5(_) => true | |
} | |
def exists(f: D => Boolean) = e match { | |
case C1(_) => false | |
case C2(_) => false | |
case C3(_) => false | |
case C4(d) => f(d) | |
case C5(_) => false | |
} | |
def flatMap[AA >: A, BB >: B, CC >: C, EE >: E, X](f: D => Either5[AA, BB, CC, X, EE]) = e match { | |
case C1(a) => C1(a) | |
case C2(b) => C2(b) | |
case C3(c) => C3(c) | |
case C4(d) => f(d) | |
case C5(e) => C5(e) | |
} | |
def map[X](f: D => X) = e match { | |
case C1(a) => C1(a) | |
case C2(b) => C2(b) | |
case C3(c) => C3(c) | |
case C4(d) => C4(f(d)) | |
case C5(e) => C5(e) | |
} | |
def filter[X](p: D => Boolean): Option[Either5[X, X, X, D, X]] = e match { | |
case C1(_) => None | |
case C2(_) => None | |
case C3(_) => None | |
case C4(d) => if(p(d)) Some(C4(d)) else None | |
case C5(_) => None | |
} | |
def toSeq = e match { | |
case C1(_) => Seq.empty | |
case C2(_) => Seq.empty | |
case C3(_) => Seq.empty | |
case C4(d) => Seq(d) | |
case C5(_) => Seq.empty | |
} | |
def toOption = e match { | |
case C1(_) => None | |
case C2(_) => None | |
case C3(_) => None | |
case C4(d) => Some(d) | |
case C5(_) => None | |
} | |
} | |
final case class _5Projection[+A, +B, +C, +D, +E](e: Either5[A, B, C, D, E]) { | |
def get = e match { | |
case C1(_) => throw new NoSuchElementException("Either._5.value on _1") | |
case C2(_) => throw new NoSuchElementException("Either._5.value on _2") | |
case C3(_) => throw new NoSuchElementException("Either._5.value on _3") | |
case C4(_) => throw new NoSuchElementException("Either._5.value on _4") | |
case C5(e) => e | |
} | |
def foreach[U](f: E => U) = e match { | |
case C1(_) => {} | |
case C2(_) => {} | |
case C3(_) => {} | |
case C4(_) => {} | |
case C5(e) => f(e) | |
} | |
def getOrElse[EE >: E](or: => EE) = e match { | |
case C1(_) => or | |
case C2(_) => or | |
case C3(_) => or | |
case C4(_) => or | |
case C5(e) => e | |
} | |
def forall(f: E => Boolean) = e match { | |
case C1(_) => true | |
case C2(_) => true | |
case C3(_) => true | |
case C4(_) => true | |
case C5(e) => f(e) | |
} | |
def exists(f: E => Boolean) = e match { | |
case C1(_) => false | |
case C2(_) => false | |
case C3(_) => false | |
case C4(_) => false | |
case C5(e) => f(e) | |
} | |
def flatMap[AA >: A, BB >: B, CC >: C, DD >: D, EE >: E, X](f: E => Either5[AA, BB, CC, DD, X]) = e match { | |
case C1(a) => C1(a) | |
case C2(b) => C2(b) | |
case C3(c) => C3(c) | |
case C4(d) => C4(d) | |
case C5(e) => f(e) | |
} | |
def map[X](f: E => X) = e match { | |
case C1(a) => C1(a) | |
case C2(b) => C2(b) | |
case C3(c) => C3(c) | |
case C4(d) => C4(d) | |
case C5(e) => C5(f(e)) | |
} | |
def filter[X](p: E => Boolean): Option[Either5[X, X, X, X, E]] = e match { | |
case C1(_) => None | |
case C2(_) => None | |
case C3(_) => None | |
case C4(_) => None | |
case C5(e) => if(p(e)) Some(C5(e)) else None | |
} | |
def toSeq = e match { | |
case C1(_) => Seq.empty | |
case C2(_) => Seq.empty | |
case C3(_) => Seq.empty | |
case C4(_) => Seq.empty | |
case C5(e) => Seq(e) | |
} | |
def toOption = e match { | |
case C1(_) => None | |
case C2(_) => None | |
case C3(_) => None | |
case C4(_) => None | |
case C5(e) => Some(e) | |
} | |
} | |
} | |
class Edge { | |
def node() = new Vertex | |
} | |
class RedEdge extends Edge { | |
override def node() = new RedVertex | |
} | |
class RedBoldEdge extends RedEdge { | |
override def node() = new RedBoldVertex | |
} | |
class GreenEdge extends Edge { | |
override def node() = new GreenVertex | |
} | |
class BlueEdge extends Edge { | |
override def node() = new BlueVertex | |
} | |
class Vertex { | |
def edge() = new Edge | |
} | |
class RedVertex extends Vertex { | |
override def edge() = new RedEdge | |
} | |
class RedBoldVertex extends RedVertex { | |
override def edge() = new RedBoldEdge | |
} | |
class GreenVertex extends Vertex { | |
override def edge() = new GreenEdge | |
} | |
class BlueVertex extends Vertex { | |
override def edge() = new BlueEdge | |
} | |
class Test(val value: Vertex) { | |
def test() = value match { case x: RedBoldVertex => C1(x.edge) | |
case x: RedVertex => C2(x.edge) | |
case x: GreenVertex => C3(x.edge) | |
case x: BlueVertex => C4(x.edge) | |
case x: Vertex => C5(x.edge) | |
} | |
} | |
object Main extends App { | |
val test0 = (new Test(new Vertex)).test() | |
val test1 = (new Test(new Vertex)).test()._5.node.edge.node.edge | |
val test2 = (new Test(new RedVertex)).test()._2.node.edge.node.edge | |
val test3 = (new Test(new RedBoldVertex)).test()._1.node.edge.node.edge | |
val test4 : Edge = (new Test(new RedBoldVertex)).test()._1.node.edge.node.edge | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment