Last active
November 26, 2021 04:05
-
-
Save Superstar64/6d4baf534d8ea2e774053bcc9eed3cdb to your computer and use it in GitHub Desktop.
Freer Monads in java
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 java.util.function.Function; | |
// straight forward port of freer monads to java | |
// see http://okmij.org/ftp/Computation/free-monad.html | |
// lightweight higher kinded polymorphism | |
// see http://ocamllabs.io/higher/lightweight-higher-kinded-polymorphism.pdf | |
interface App<F,A> {} | |
// freer monads have an exstential type | |
// so pattern matching on them requires a rank n type | |
interface View<R, F, A> { | |
R pure(A pure); | |
<X> R impure(App<F, X> now, Function<X, Freer<F, A>> after); | |
} | |
// the 2 constructors for freer monads | |
class Pure<F, A> extends Freer<F, A> { | |
final A pure; | |
Pure(A pure) { | |
this.pure = pure; | |
} | |
<R> R match(View<R, F, A> view) { | |
return view.pure(pure); | |
} | |
} | |
class Impure<X, F, A> extends Freer<F, A> { | |
final App<F, X> now; | |
final Function<X, Freer<F,A>> after; | |
Impure(App<F, X> now, Function<X, Freer<F, A>> after) { | |
this.now = now; | |
this.after = after; | |
} | |
<R> R match(View<R, F, A> view) { | |
return view.impure(now, after); | |
} | |
} | |
public abstract class Freer<F, A> implements App<App<Freer<?, ?>, F>, A> { | |
abstract <R> R match(View<R, F, A> view); | |
// monadic bind | |
final <B> Freer<F, B> flatMap(Function<A, Freer<F, B>> lastly) { | |
return match(new View<Freer<F, B>, F, A>() { | |
public Freer<F, B> pure(A pure) { | |
return lastly.apply(pure); | |
} | |
public <X> Freer<F, B> impure(App<F, X> now, Function<X, Freer<F, A>> after) { | |
return new Impure<X, F, B>(now, x -> after.apply(x).flatMap(lastly) ); | |
} | |
}); | |
} | |
// convert a F a to Freer F a | |
static <F, A> Freer<F, A> eta(App<F, A> effect) { | |
return impure(effect, Freer::pure); | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment