# Progressions of concision

January 30, 2016

## `Either`

Let's implement a simple sum type, `Either`, in a few polymorphic languages.

### Java

``````class NoValueException extends Exception { }

interface Either<A,B> {

boolean isLeft();
boolean isRight();

public A leftValue() throws NoValueException;
public B rightValue() throws NoValueException;

}

class Left<A,B> implements Either<A,B> {

public final A a;

public Left(A a) {
this.a = a;
}

@Override
public boolean isLeft() {
return true;
}

@Override
public boolean isRight() {
return false;
}

@Override
public A leftValue() throws NoValueException {
return a;
}

@Override
public B rightValue() throws NoValueException {
throw new NoValueException();
}

@Override
public boolean equals(Object x) {
}

@Override
public int hashCode() {
}

@Override
public String toString() {
return "Left(" + a.toString() + ")";
}

}

class Right<A,B> implements Either<A,B> {

public final B b;

public Right(B b) {
this.b = b;
}

@Override
public boolean isLeft() {
return false;
}

@Override
public boolean isRight() {
return true;
}

@Override
public A leftValue() throws NoValueException {
throw new NoValueException();
}

@Override
public B rightValue() throws NoValueException {
return b;
}

@Override
public boolean equals(Object x) {
}

@Override
public int hashCode() {
}

@Override
public String toString() {
return "Right(" + b.toString() + ")";
}

}``````

Lines of code: 75.

### Scala

``````sealed trait Either[A,B]
case class Left[A,B](a: A) extends Either[A,B]
case class Right[A,B](b: B) extends Either[A,B]``````

Lines of code: 3.

``data Either a b = Left a | Right b deriving (Eq, Show)``

Lines of code: 1.

## `RightBiasedEither`

`Either` is useful for storing a value of one of two types, but it isn't very useful otherwise.

Let's make it composable by adding `map`, `ap`, and `flatMap` (a.k.a. `fmap`, `<*>`, and `>>=`), and biasing it to `Right`.

### Java

``````class NoValueException extends Exception { }

interface RightBiasedEither<A,B> {

boolean isLeft();
boolean isRight();

A leftValue() throws NoValueException;
B rightValue() throws NoValueException;

<C> RightBiasedEither<A,C> map(Function<B,C> f);
<C> RightBiasedEither<A,C> ap(RightBiasedEither<A,Function<B,C>> fe);
<C> RightBiasedEither<A,C> flatMap(Function<B,RightBiasedEither<A,C>> f);

}

class Left<A,B> implements RightBiasedEither<A,B> {

public final A a;

public Left(A a) {
this.a = a;
}

@Override
public boolean isLeft() {
return true;
}

@Override
public boolean isRight() {
return false;
}

@Override
public A leftValue() throws NoValueException {
return a;
}

@Override
public B rightValue() throws NoValueException {
throw new NoValueException();
}

@Override
public boolean equals(Object x) {
}

@Override
public int hashCode() {
}

@Override
public String toString() {
return "Left(" + a.toString() + ")";
}

@Override
public <C> RightBiasedEither<A,C> map(Function<B,C> f) {
return new Left<>(a);
}

@Override
public <C> RightBiasedEither<A,C> ap(RightBiasedEither<A,Function<B,C>> fe) {
return new Left<>(a);
}

@Override
public <C> RightBiasedEither<A,C> flatMap(Function<B,RightBiasedEither<A,C>> f) {
return new Left<>(a);
}

}

class Right<A,B> implements RightBiasedEither<A,B> {

public final B b;

public Right(B b) {
this.b = b;
}

@Override
public boolean isLeft() {
return false;
}

@Override
public boolean isRight() {
return true;
}

@Override
public A leftValue() throws NoValueException {
throw new NoValueException();
}

@Override
public B rightValue() throws NoValueException {
return b;
}

@Override
public boolean equals(Object x) {
}

@Override
public int hashCode() {
}

@Override
public String toString() {
return "Right(" + b.toString() + ")";
}

@Override
public <C> RightBiasedEither<A,C> map(Function<B,C> f) {
return new Right<>(f.apply(b));
}

@Override
public <C> RightBiasedEither<A,C> ap(RightBiasedEither<A,Function<B,C>> fe) {
return fe.map((f) -> f.apply(b));
}

@Override
public <C> RightBiasedEither<A,C> flatMap(Function<B,RightBiasedEither<A,C>> f) {
return f.apply(b);
}

}``````

Lines of code: 102.

### Scala

``````trait RightBiasedEither[A,B] {
def map[C](f: B => C): RightBiasedEither[A,C]
def ap[C](fe: RightBiasedEither[A,B => C]): RightBiasedEither[A,C]
def flatMap[C](f: B => RightBiasedEither[A,C]): RightBiasedEither[A,C]
}

case class Left[A,B](a: A) extends RightBiasedEither[A,B] {
def map[C](f: B => C): RightBiasedEither[A,C] = Left(a)
def ap[C](fe: RightBiasedEither[A,B => C]): RightBiasedEither[A,C] = Left(a)
def flatMap[C](f: B => RightBiasedEither[A,C]): RightBiasedEither[A,C] = Left(a)
}

case class Right[A,B](b: B) extends RightBiasedEither[A,B] {
def map[C](f: B => C): RightBiasedEither[A,C] = Right(f(b))
def ap[C](fe: RightBiasedEither[A,B => C]): RightBiasedEither[A,C] = fe.map(f => f(b))
def flatMap[C](f: B => RightBiasedEither[A,C]): RightBiasedEither[A,C] = f(b)
}``````

Lines of code: 15.

``````data RightBiasedEither a b = Left a | Right b deriving (Eq, Show)

instance Functor (RightBiasedEither a) where
fmap f e = e >>= (\x -> pure (f x))

instance Applicative (RightBiasedEither a) where
pure b = Right b
(<*>) fe e = fe >>= (\f -> fmap f e)

(>>=) (Right b) f = f b
(>>=) (Left a) _  = Left a``````

Lines of code: 9.