Skip to content

Instantly share code, notes, and snippets.

@mariogarcia
Last active August 29, 2015 14:04
Show Gist options
  • Save mariogarcia/af88669efd1057654f51 to your computer and use it in GitHub Desktop.
Save mariogarcia/af88669efd1057654f51 to your computer and use it in GitHub Desktop.
Functor, Appllicative y Monad
import groovy.transform.Immutable
// PROTOCOLO
interface Functor {
Functor fmap(Closure fn)
}
interface Applicative {
Applicative fapply(Applicative afn)
Applicative pure(Object v)
Object getValue()
}
interface Monad {
Monad bind(Closure<Monad> mfn)
}
// API PUBLICO
class Dogs {
static fmap(Closure fn, Functor fv) {
return fv.fmap(fn)
}
static fapply(Applicative afn, Applicative av) {
return afn.fapply(av)
}
static pure(Object ctx, Object value) {
// ctx es cualquier applicative o functor, solo queremos saber el tipo
return ctx.pure(value)
}
static bind(Monad mv, Closure<Monad> fn) {
//fn.delegate.metaClass.pure = mv.metaClass.pure
return mv.bind(fn)
}
}
enum Type {
LEFT, RIGHT
}
// IMPLEMENTACION DE FUNCTOR (UNA CUALQUIERA)
//@Immutable
class Either implements Functor, Applicative, Monad {
Object value
Type type
Functor fmap(Closure fn) {
if(type == Type.LEFT) return this
return right(fn(value))
}
Applicative fapply(Applicative av) {
if(type == Type.LEFT) return this
return (Applicative) av.fmap(value)
}
Applicative pure(Object v) {
return Either.right(v)
}
Monad bind(Closure<Monad> fn) {
if(type == Type.LEFT) return this
return fn(value)
}
static right(Object v) {
new Either(value: v, type: Type.RIGHT)
}
static left(Object v) {
new Either(value: v, type: Type.LEFT)
}
String toString() {
"#<Either [$value $type]>"
}
}
// a -> b ==-a -> M b
// a -> b -> c == M a -> M b -> M c
def inc = { Either.right(it + 1) }
def ainc = Either.right(inc)
println "APPLICATIVE:" + Dogs.fapply(Either.left(null), Either.right(1))
println "FUNCTOR:" + Dogs.fmap(inc, Either.right(1))
println "MONAD:" + Dogs.bind(Either.right(1), { x -> Either.right(inc(x)) })
Dogs.bind(Either.right(1), { x ->
Dogs.bind(Either.right(2), { y ->
Either.right(x + y)
})
})
>>=(Either.right(1), inc, inc, inc)
(mlet [x Either.right(1)
y Either.right(2)]
(Either.right (x + y)))
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment