Last active
August 29, 2015 14:04
-
-
Save mariogarcia/af88669efd1057654f51 to your computer and use it in GitHub Desktop.
Functor, Appllicative y Monad
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
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