Skip to content

Instantly share code, notes, and snippets.

@hannestyden
Last active December 4, 2018 12:18
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save hannestyden/f302cc6de2b0c7b427cdcc140930a172 to your computer and use it in GitHub Desktop.
Save hannestyden/f302cc6de2b0c7b427cdcc140930a172 to your computer and use it in GitHub Desktop.
Beither
abstract class Beither[+A, +B] {
// From German "beide" and English "either" => "beither".
// Preferably pronounced as German "Beißer".
def left = Beither.LeftProjection(this)
def right = Beither.RightProjection(this)
def both = Beither.BothProjection(this)
}
case class Left[+A, +B](a: A) extends Beither[A, B]
case class Right[+A, +B](b: B) extends Beither[A, B]
case class Both[+A, +B](a: A, b: B) extends Beither[A, B]
object Beither {
case class BothProjection[+A, +B](e: Beither[A, B]) {
def get = e match {
case Both(a, b) => (a, b)
case _ => throw new NoSuchElementException("Beither.both.value on Right or Left")
}
}
case class LeftProjection[+A, +B](e: Beither[A, B]) {
def get = e match {
case Left(a) => a
case Both(a, _) => a
case Right(_) => throw new NoSuchElementException("Beither.left.value on Right")
}
}
case class RightProjection[+A, +B](e: Beither[A, B]) {
def get = e match {
case Left(_) => throw new NoSuchElementException("Beither.right.value on Left")
case Right(b) => b
case Both(_, b) => b
}
}
}
val a: Beither[String, Int] = Right(1)
val b: Beither[String, Int] = Left("a")
val c: Beither[String, Int] = Both("a", 1)
c.left.get // String = a
c.right.get // Int = 1
c.both.get // (String, Int) = (a,1)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment