crazy4groovy
1/20/2017 - 9:41 AM

Either type in Groovy as a special implementation of the generic sum type (works the same in Java)

Either type in Groovy as a special implementation of the generic sum type (works the same in Java)

// Either type in Groovy as a special implementation of the generic sum type
// see: Phil Wadler at LambdaWorld 2016: youtu.be/V10hzjgoklA


import java.util.function.*
import groovy.transform.*

interface Either<A,B> {
    public <C> C match (Function <A,C> leftCase, Function <B,C> rightCase)
}

@Canonical
class Left<A,B> implements Either<A,B> {
    final A x
    public <C> C match (Function <A,C> leftCase, Function <B,C> rightCase) {
        leftCase.apply(x)
    }    
}

@Canonical
class Right<A,B> implements Either<A,B> {
    final B x
    public <C> C match (Function <A,C> leftCase, Function <B,C> rightCase) {
        rightCase.apply(x)
    }    
}

Either<String, Number> divide(Number dividend, Number divisor) {
    if (0 == divisor) return new Left("Sorry, cannot divide $dividend by 0")
    new Right(dividend / divisor)
}

String format(Either<String, Number> either) {    
    either.match (
        { it },            // left  case
        { Number n -> n }  // right case
    )
}

assert format(divide(84, 0)) == "Sorry, cannot divide 84 by 0"
assert format(divide(84, 2)) == "42"     // note the String type!

// now the fun starts
// we can make this a functor, applicative, monad ...