Skip to content

Instantly share code, notes, and snippets.

@frabbit
Last active December 31, 2015 22:39
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save frabbit/8054930 to your computer and use it in GitHub Desktop.
Save frabbit/8054930 to your computer and use it in GitHub Desktop.
Monad Transformers
using FunctorSyntax;
using ArrayT;
enum Either<L,R> {
Left(l:L);
Right(r:R);
}
interface Functor<F> {
public function fmap<A,B>(x:F<A>, f:A->B):F<B>;
}
class EitherFunctor<L> implements Functor<Either<L, In>>
{
public function new () {}
public function fmap<A,B>(x:Either<L, A>, f:A->B):Either<L, B> {
return switch (x) {
case Right(r): Right(f(r));
case Left(l): Left(l);
}
}
}
class ArrayFunctor implements Functor<Array<In>> {
public function new () {}
public inline function fmap<S,T>(a:Array<S>, f:S->T):Array<T> {
return a.map(f);
}
}
abstract ArrayT<M, A>(M<Array<A>>)
{
public function new (x:M<Array<A>>) {
this = x;
}
public function unwrap ():M<Array<A>> {
return this;
}
public static function runT <M1,A1>(a:ArrayT<M1,A1>):M1<Array<A1>>
{
return a.unwrap();
}
public static function arrayT <M1,A1>(a:M1<Array<A1>>):ArrayT<M1,A1>
{
return new ArrayT(a);
}
}
class ArrayTFunctor<M> implements Functor<ArrayT<M,In>>
{
var functorM:Functor<M>;
public function new (functorM:Functor<M>)
{
this.functorM = functorM;
}
public function fmap<A,B>(v:ArrayT<M, A>,f:A->B):ArrayT<M, B>
{
function g (a:Array<A>) return a.map(f);
return functorM.fmap(v.runT(), g).arrayT();
}
}
class FunctorSyntax {
public static function fmap<M, S, T>(x:M<S>, f:S->T, m:Functor<M>):M<T> {
return m.fmap(x, f);
}
}
class Main {
public static function main ()
{
var func = new ArrayTFunctor(new ArrayTFunctor(new EitherFunctor()));
var e = Right([[1]]);
var r2 = e.arrayT().arrayT().fmap(function (x) return x+1, func).runT().runT();
trace(r2); // traces Right([[2]])
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment