Skip to content

Instantly share code, notes, and snippets.

@DaveGit
Created May 15, 2012 21:59
Show Gist options
  • Save DaveGit/2705479 to your computer and use it in GitHub Desktop.
Save DaveGit/2705479 to your computer and use it in GitHub Desktop.
Either with arity 5
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