Skip to content

Instantly share code, notes, and snippets.

@mariogarcia
Last active August 29, 2015 14:04
Show Gist options
  • Save mariogarcia/560632038bf3dd8d888d to your computer and use it in GitHub Desktop.
Save mariogarcia/560632038bf3dd8d888d to your computer and use it in GitHub Desktop.
New version of categories research
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