Last active
August 29, 2015 14:04
-
-
Save mariogarcia/560632038bf3dd8d888d to your computer and use it in GitHub Desktop.
New version of categories research
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
interface Fn<I,O> { | |
O execute(I i) | |
} | |
// applies a function to a value | |
// TODO while I think functions could be parametrized | |
// functors should not. Functions are a special case | |
// of functors | |
interface Functor<I,O> { | |
I getValue() | |
Functor<I,O> fmap(Fn<I,O> fn) | |
} | |
// applies a function to a value with a given context | |
interface Applicative<I,O> extends Functor<I,O> { | |
Applicative<I,O> fapply(Applicative<I,O> afn) | |
} | |
interface Monad<I,O> extends Applicative<I,O> { | |
Monad<I,O> bind(Fn<I,Monad<I,O>> fn) | |
} | |
@groovy.transform.ToString | |
class Either<I,O> implements Monad<I,O> { | |
static enum Type { RIGHT, LEFT } | |
O value | |
Type type | |
Either fmap(Fn<I,O> fn) { | |
return isLeft() ? this : right(fn.execute(value)) | |
} | |
/* | |
* Applicative applies a function with some context | |
* | |
* Dogs.apply(Either.right(inc), Either.right(1)) | |
* | |
* Is this example the context is the object wrapping | |
* the function. With Either the context tells whether | |
* the function can be applied (RIGHT) or not to be | |
* applied (LEFT). | |
* | |
*/ | |
Either fapply(Applicative<I,O> afn) { | |
return isLeft() ? this : this.fmap(afn.value) | |
} | |
Either bind(Fn<I, Monad<I,O>> fn) { | |
return isLeft() ? this : fn.execute(value) | |
} | |
Boolean isLeft() { | |
return type == Type.LEFT | |
} | |
static <I,O> Either<I,O> right(O o) { | |
return new Either<I,O>(value: o, type: Type.RIGHT) | |
} | |
static <I,O> Either<I,O> left(O o) { | |
return new Either<I,O>(value: o, type: Type.LEFT) | |
} | |
} | |
Fn fn = { it.capitalize() } | |
Fn up = { it.toUpperCase() } | |
Either | |
.right('hi') | |
.fapply(Either.right(fn)) | |
.fmap(up) | |
.value |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment