Awesome Open Source
Awesome Open Source


Purefun logo

Build Status Codacy Badge Build Status Join the chat at

This module was developed as the core of the zeromock project. It defines all the basic classes and interfaces used in the rest of the project.

Initially the module only held a few basic interfaces and it has grown to become an entire functional programming library (well, a humble one), and now is an independent library.

Working in this library helped me to learn and understand some important concepts of functional programming, and over time I implemented higher kinded types and type classes in Java. I don't know if this will be helpful for somebody, but the work is here to everyone want to use it.

Finally, I have to say thanks to vavr library author, this library is largely inspired in his work, and also to Scala standard library authors. I don't want to forget some of the projects I've used as reference: Arrow and cats for type classes implementation, fs2 for stream processing, and ZIO to implement my own version in Java. Their awesome work help me a lot.


This project is not ready to be used in production, I use it to learn functional programming concepts by my self, but, if you want to use it, use it at your own risk. Anyway if you think is useful for you, go ahead, also any feedback and PR are very welcome.

Higher Kinded Types

In this project I have implemented some patterns of functional programming that need Higher Kinded Types. In Java there are not such thing, but it can be simulated using a especial codification of types.

In Scala we can define a higher kinded typed just like this Monad[F[_]] but in Java it can be codified like this Monad<F extends Witness>. Witness is a simple mark interface. Then we can define a type using a special codification like this:

interface SomeType<T> extends SomeTypeOf<T> { }

// Boilerplate
interface SomeTypeOf<T> implements Kind<SomeType_, T> {

  default Kind<SomeType_, T> kind() {
    return this;

  // this is a safe cast
  static SomeType<T> narrowK(Kind<SomeType_, T> hkt) {
    return (SomeType<T>) hkt;
  static Fixer<Kind<SomeType_, T>, SomeType<T>> toSomeType() {
    return SomeType::narrowK;

final class SomeType_ extends Witness {
  private SomeType_() {}

It can be triky but, in the end is easy to work with. By the way, I tried to hide this details to the user of the library. Except with type classes because is the only way to implement them correctly.

So, there are interfaces to encode kinds of 1, 2 and 3 types. It can be defined types for 4, 5 or more types, but it wasn't necessary to implement the library.

Annotation Processor

In order to simplify working with higher kinded types, in the last version I've included an annotation processor to generate all this boilerplate code:

interface SomeType<T> extends SomeTypeOf<T> { }

With this annotation, all the above code, is generated automatically.

Data types


Is an alternative to Optional of Java standard library. It can contains two values, a some or a none

Option<String> some = Option.some("Hello world");

Option<String> none = Option.none();


Is an implementation of scala Try in Java. It can contains two values, a success or a failure.

Try<String> success = Try.success("Hello world");

Try<String> failure = Try.failure(new RuntimeException("Error"));


Is an implementation of scala Either in Java.

Either<Integer, String> right = Either.right("Hello world");

Either<Integer, String> left = Either.left(100);


This type represents two different states, valid or invalid, an also it allows to combine several validations using map2 to map5 methods.

Validation<String, String> name = Validation.valid("John Smith");
Validation<String, String> email = Validation.valid("[email protected]");

// Person has a constructor with two String parameters, name and email.
Valdation<Sequence<String>, Person> person = Validation.map2(name, email, Person::new);


A object with a phantom parameter:

Const<String, Integer> constInt = Const.of("Hello world!");

Const<String, Float> constFloat = constInt.retag();

assertEquals("Hello world!", constFloat.value());


This is an experimental implementation of Future. Computations are executed in another thread inmediatelly.

Future<String> future = Future.success("Hello world!");

Future<String> result = future.flatMap(string ->;

assertEquals(Try.success("HELLO WORLD!"), result.await());


These classes allow to hold some values together, as tuples. There are tuples from 1 to 5.

Tuple1<String> tuple1 = Tuple.of("Hello world");

Tuple2<String, Integer> tuple2 = Tuple.of("John Smith", 100);

Data structures

Java doesn't define immutable collections, so I have implemented some of them.


Is the equivalent to java Collection interface. It defines all the common methods.


It represents a linked list. It has a head and a tail.


It represents a set of elements. This elements cannot be duplicated.


It represents an array. You can access to the elements by its position in the array.


This class represents a hash map.


This class represents a binary tree.


This class represents a binary tree map.


Also I have implemented some Monads that allows to combine some operations.

State Monad

Is the traditional State Modad from FP languages, like Haskel or Scala. It allows to combine operations over a state. The state should be a immutable class. It recives an state and generates a tuple with the new state and an intermediate result.

State<ImmutableList<String>, Option<String>> read = State.state(list -> Tuple.of(list.tail(), list.head()));

Tuple<ImmutableList<String>, Option<String>> result ="a", "b", "c"));

assertEquals(Tuple.of(ImmutableList.of("b", "c"), Option.some("a")), result);

Reader Monad

This is an implementation of Reader Monad. It allows to combine operations over a common input. It can be used to inject dependencies.

Reader<ImmutableList<String>, String> read2 = Reader.reader(list -> list.tail().head().orElse(""));

String result = read2.eval(ImmutableList.of("a", "b", "c"));

assertEqual("b", result);

Writer Monad

It allow to combine operations over a common output.

Writer<ImmutableList<String>, Integer> writer = Writer.<String, Integer>listPure(5)
    .flatMap(value -> listWriter("add 5", value + 5))
    .flatMap(value -> listWriter("plus 2", value * 2));

assertAll(() -> assertEquals(Integer.valueOf(20), writer.getValue()),
          () -> assertEquals(listOf("add 5", "plus 2"), writer.getLog()));

IO Monad

This is a experimental implementation of IO Monad in java. Inspired in this work.

IO<Unit> echo = Console.print("write your name")
  .flatMap(name -> Console.print("Hello " + name))



Implements recursion using an iteration and is stack safe.

private Trampoline<Integer> fibLoop(Integer n) {
if (n < 2) {
  return Trampoline.done(n);
return Trampoline.more(() -> fibLoop(n - 1)).flatMap(x -> fibLoop(n - 2).map(y -> x + y));


Free Monad

Finally, after hours of hard coding, I managed to implement a Free monad. This is a highly unstable implementation and I have implemented because it can be implemented. Inspired in this work.

Free<IOProgram_, Unit> echo =
  IOProgram.write("what's your name?")
    .flatMap(text -> IOProgram.write("Hello " + text))

Kind<IO_, Unit> foldMap = echo.foldMap(IOInstances.monad(), new IOProgramInterperter());


Free Applicative

Similar to Free monad, but allows static analysis without to run the program.

FreeAp<DSL_, Tuple5<Integer, Boolean, Double, String, Unit>> tuple =
        DSL.readString("hola mundo"),

Kind<Id_, Tuple5<Integer, Boolean, Double, String, Unit>> map =
    tuple.foldMap(idTransform(), IdInstances.applicative());

assertEquals(Id.of(Tuple.of(2, false, 2.1, "hola mundo", unit())), map.fix(toId()));

Monad Transformers


Monad Transformer for Option type

OptionT<IO_, String> some = OptionT.some(IO.monad(), "abc");

OptionT<IO_, String> map = some.flatMap(value -> OptionT.some(IOInstances.monad(), value.toUpperCase()));

assertEquals("ABC", map.get().fix(toIO()).unsafeRunSync());


Monad Transformer for Either type

EitherT<IO_, Nothing, String> right = EitherT.right(IO.monad(), "abc");

EitherT<IO_, Nothing, String> map = right.flatMap(value -> EitherT.right(IOInstances.monad(), value.toUpperCase()));

assertEquals("ABC", map.get().fix(toIO()).unsafeRunSync());


Monad Transformer for State type

StateT<IO_, ImmutableList<String>, Unit> state =

IO<Tuple2<ImmutableList<String>, Unit>> result =;

assertEquals(Tuple.of(listOf("a", "b", "c"), unit()), result.unsafeRunSync());


Monad Transformer for Writer type

WriterT<Id_, Sequence<String>, Integer> writer =
    WriterT.<Id_, Sequence<String>, Integer>pure(monoid, monad, 5)
    .flatMap(value -> lift(monoid, monad, Tuple.of(listOf("add 5"), value + 5)))
    .flatMap(value -> lift(monoid, monad, Tuple.of(listOf("plus 2"), value * 2)));

assertAll(() -> assertEquals(Id.of(Integer.valueOf(20)), writer.getValue()),
          () -> assertEquals(Id.of(listOf("add 5", "plus 2")), writer.getLog()));


Also I implemented the Kleisli composition for functions that returns monadic values like Option, Try or Either.

Kleisli<Try_, String, Integer> toInt = Kleisli.lift(Try.monad(), Integer::parseInt);
Kleisli<Try_, Integer, Double> half = Kleisli.lift(Try.monad(), i -> i / 2.);

Kind<Try_, Double> result = toInt.compose(half).run("123");

assertEquals(Try.success(61.5), result);


An experimental version of a Stream like scala fs2 project.

StreamOf<IO_> streamOfIO = Stream.ofIO();

IO<String> readFile = streamOfIO.eval(IO.of(() -> reader(file)))
  .flatMap(reader -> streamOfIO.iterate(() -> Option.of(() -> readLine(reader))))
  .foldLeft("", (a, b) -> a + "\n" + b)
  .recoverWith(UncheckedIOException.class, cons("--- file not found ---"));

String content = readFile.unsafeRunSync();


An experimental version of ZIO.

ZIO<Console, Throwable, Unit> echoProgram =
  Console.println("what's your name?")
      .flatMap(name -> Console.println("Hello " + name));

interface Console {

  <R extends Console> Console.Service<R> console();

  static ZIO<Console, Throwable, String> readln() {
    return ZIO.accessM(env -> env.console().readln());

  static ZIO<Console, Throwable, Unit> println(String text) {
    return ZIO.accessM(env -> env.console().println(text));

  interface Service<R extends Console> {
    ZIO<R, Throwable, String> readln();

    ZIO<R, Throwable, Unit> println(String text);

Additionally, there are aliases for some ZIO special cases:

UIO<T>      =>  ZIO<Any, Nothing, T>
EIO<E, T>   =>  ZIO<Any, E, T>
Task<T>     =>  ZIO<Any, Throwable, T>
RIO<R, T>   =>  ZIO<R, Throwable, T>
URIO<T>     =>  ZIO<R, Nothing, T>

Algebraic Effects

Also, I have implemented a version of delimited control monad based in this project. With this monad, you can implement algebraic effects. Example:

  // the effect
  interface Amb {
    Control<Boolean> flip();

  // the program, if true then 2 else 3
  Control<Integer> program(Amb amb) {
    return amb.flip().map(x -> x ? 2 : 3);

  void test() {
    Control<ImmutableList<Integer>> handled = ambList(this::program);

    assertEquals(listOf(2, 3),;

  <R> Control<ImmutableList<R>> ambList(Function1<Amb, Control<R>> program) {
    return new AmbList<R>().apply(amb -> program.apply(amb).map(ImmutableList::of));

  final class AmbList<R> implements Handler<ImmutableList<R>, Amb>, Amb {

    public Amb effect() { return this; }

    public Control<Boolean> flip() {
      return use(resume ->
          resume.apply(true) // first flip return true
            .flatMap(ts -> resume.apply(false) // second flip return false

Type Classes

With higher kinded types simulation we can implement typeclases.

                       Invariant -- Contravariant
       SemigroupK           Functor -- Comonad
           |               /       \
         MonoidK   _ Applicative   Traverse -- Foldable
           |      /      |      \
       Alternative    Selective  ApplicativeError
                         |        |
  MonadWriter          Monad      |
        \________________|        |
        /          /      \      / 
  MonadState  MonadReader  MonadError_____
                               \          \
                            MonadThrow  Bracket
                                  \      /
                        Defer -- MonadDefer -- Timer


public interface Functor<F extends Witness> extends Invariant<F> {

  <T, R> Kind<F, R> map(Kind<F, T> value, Function1<T, R> map);


public interface Applicative<F extends Witness> extends Functor<F> {

  <T> Kind<F, T> pure(T value);

  <T, R> Kind<F, R> ap(Kind<F, T> value, Kind<F, Function1<T, R>> apply);

  default <T, R> Kind<F, R> map(Kind<F, T> value, Function1<T, R> map) {
    return ap(value, pure(map));


public interface Selective<F extends Witness> extends Applicative<F> {

  <A, B> Kind<F, B> select(Kind<F, Either<A, B>> value, Kind<F, Function1<A, B>> apply);

  default <A, B, C> Kind<F, C> branch(Kind<F, Either<A, B>> value,
                                      Kind<F, Function1<A, C>> applyA,
                                      Kind<F, Function1<B, C>> applyB) {
    Kind<F, Either<A, Either<B, C>>> abc = map(value, either ->;
    Kind<F, Function1<A, Either<B, C>>> fabc = map(applyA, fb -> fb.andThen(Either::right));
    return select(select(abc, fabc), applyB);


public interface Monad<F extends Witness> extends Selective<F> {

  <T, R> Kind<F, R> flatMap(Kind<F, T> value, Function1<T, ? extends Kind<F, R>> map);

  default <T, R> Kind<F, R> map(Kind<F, T> value, Function1<T, R> map) {
    return flatMap(value, map.andThen(this::pure));

  default <T, R> Kind<F, R> ap(Kind<F, T> value, Kind<F, Function1<T, R>> apply) {
    return flatMap(apply, map -> map(value, map));

  default <A, B> Kind<F, B> select(Kind<F, Either<A, B>> value, Kind<F, Function1<A, B>> apply) {
    return flatMap(value, either -> either.fold(a -> map(apply, map -> map.apply(a)), this::<B>pure));


It represents a binary operation over a type.

public interface Semigroup<T> {
  T combine(T t1, T t2);

There are instances for strings and integers.


Extends Semigroup adding a zero operation that represent an identity.

public interface Monoid<T> extends Semigroup<T> {
  T zero();

There are instances for strings and integers.


It represents a Semigroup but defined for a kind, like a List, so it extends a regular Semigroup.


The same like SemigroupK but for a Monoid.


public interface Invariant<F extends Witness> {
  <A, B> Kind<F, B> imap(Kind<F, A> value, Function1<A, B> map, Function1<B, A> comap);


public interface Contravariant<F extends Witness> extends Invariant<F> {
  <A, B> Kind<F, B> contramap(Kind<F, A> value, Function1<B, A> map);


public interface Bifunctor<F extends Witness> {
  <A, B, C, D> Kind<Kind<F, C>, D> bimap(Kind<Kind<F, A>, B> value, Function1<A, C> leftMap, Function1<B, D> rightMap);


public interface Profunctor<F extends Witness> {
  <A, B, C, D> Kind<Kind<F, C>, D> dimap(Kind<Kind<F, A>, B> value, Function1<C, A> contramap, Function1<B, D> map);

Applicative Error

public interface ApplicativeError<F extends Witness, E> extends Applicative<F> {

  <A> Kind<F, A> raiseError(E error);

  <A> Kind<F, A> handleErrorWith(Kind<F, A> value, Function1<E, ? extends Kind<F, A>> handler);

Monad Error

public interface MonadError<F extends Witness, E> extends ApplicativeError<F, E>, Monad<F> {

  default <A> Kind<F, A> ensure(Kind<F, A> value, Producer<E> error, Matcher1<A> matcher) {
    return flatMap(value, a -> matcher.match(a) ? pure(a) : raiseError(error.get()));

Monad Throw

public interface MonadThrow<F extends Witness> extends MonadError<F, Throwable> {



public interface MonadReader<F extends Witness, R> extends Monad<F> {

  Kind<F, R> ask();

  default <A> Kind<F, A> reader(Function1<R, A> mapper) {
    return map(ask(), mapper);


public interface MonadState<F extends Witness, S> extends Monad<F> {
  Kind<F, S> get();
  Kind<F, Unit> set(S state);

  default Kind<F, Unit> modify(Operator1<S> mapper) {
    return flatMap(get(), s -> set(mapper.apply(s)));

  default <A> Kind<F, A> inspect(Function1<S, A> mapper) {
    return map(get(), mapper);

  default <A> Kind<F, A> state(Function1<S, Tuple2<S, A>> mapper) {
    return flatMap(get(), s -> mapper.apply(s).applyTo((s1, a) -> map(set(s1), x -> a)));


public interface MonadWriter<F extends Witness, W> extends Monad<F> {

  <A> Kind<F, A> writer(Tuple2<W, A> value);
  <A> Kind<F, Tuple2<W, A>> listen(Kind<F, A> value);
  <A> Kind<F, A> pass(Kind<F, Tuple2<Operator1<W>, A>> value);

  default Kind<F, Unit> tell(W writer) {
    return writer(Tuple.of(writer, unit()));


public interface Comonad<F extends Witness> extends Functor<F> {

  <A, B> Kind<F, B> coflatMap(Kind<F, A> value, Function1<Kind<F, A>, B> map);

  <A> A extract(Kind<F, A> value);

  default <A> Kind<F, Kind<F, A>> coflatten(Kind<F, A> value) {
    return coflatMap(value, identity());


public interface Foldable<F extends Witness> {

  <A, B> B foldLeft(Kind<F, A> value, B initial, Function2<B, A, B> mapper);

  <A, B> Eval<B> foldRight(Kind<F, A> value, Eval<B> initial, Function2<A, Eval<B>, Eval<B>> mapper);


public interface Traverse<F extends Witness> extends Functor<F>, Foldable<F> {

  <G extends Witness, T, R> Kind<G, Kind<F, R>> traverse(Applicative<G> applicative, Kind<F, T> value,
      Function1<T, ? extends Kind<G, R>> mapper);


public interface Semigroupal<F extends Witness> {

  <A, B> Kind<F, Tuple2<A, B>> product(Kind<F, A> fa, Kind<F, B> fb);


public interface Defer<F extends Witness> {

  <A> Kind<F, A> defer(Producer<Kind<F, A>> defer);


public interface Bracket<F extends Witness, E> extends MonadError<F, E> {

  <A, B> Kind<F, B> bracket(Kind<F, A> acquire, Function1<A, ? extends Kind<F, B>> use, Consumer1<A> release);


public interface MonadDefer<F extends Witness> extends MonadThrow<F>, Bracket<F, Throwable>, Defer<F>, Timer<F> {

  default <A> Kind<F, A> later(Producer<A> later) {
    return defer(() -> Try.of(later::get).fold(this::raiseError, this::pure));


public interface Async<F extends Witness> extends MonadDefer<F> {
  <A> Kind<F, A> async(Consumer1<Consumer1<Try<A>>> consumer);



public interface Timer<F extends Witness> {

  Kind<F, Unit> sleep(Duration duration);


It represents a natural transformation between two different kinds.

public interface FunctionK<F extends Witness, G extends Witness> {
  <T> Kind<G, T> apply(Kind<F, T> from);


        /       \
    Lens        Prism
        \       /


An Iso is an optic which converts elements of some type into elements of other type without loss. In other words, it's isomorphic.

Point point = new Point(1, 2);

Iso<Point, Tuple2<Integer, Integer>> pointToTuple = 
  Iso.of(p -> Tuple.of(p.x, p.y), 
         t -> new Point(t.get1(), t.get2()));

assertEquals(point, pointToTuple.set(pointToTuple.get(point)));


A Lens is an optic used to zoom inside a structure. In other words, it's an abstraction of a setter and a getter but with immutable objects.

Lens<Employee, String> nameLens = Lens.of(Employee::getName, Employee::withName);

Employee pepe = new Employee("pepe");

assertEquals("pepe", nameLens.get(pepe));
assertEquals("paco", nameLens.get(nameLens.set(pepe, "paco")));

We can compose Lenses to get deeper inside. For example, if we add an attribute of type Address into Employee. We can create a lens to access the city name of the address of the employee.

Lens<Employee, Address> addressLens = Lens.of(Employee::getAddress, Employee::withAddress);
Lens<Address, String> cityLens = Lens.of(Address::getCity, Address::withCity);
Lens<Employee, String> cityAddressLens = addressLens.compose(cityLens);

Employee pepe = new Employee("pepe", new Address("Madrid"));

assertEquals("Madrid", cityAddressLens.get(pepe));


A Prism is a lossless invertible optic that can see into a structure and optionally find a value.

Function1<String, Option<Integer>> parseInt = ...; // is a method that only returns a value when the string can be parsed

Prism<String, Integer> stringToInteger = Prism.of(parseInt, String::valueOf);

assertEquals(Option.some(5), stringToInteger.getOption("5"));
assertEquals(Option.none(), stringToInteger.getOption("a"));
assertEquals("5", stringToInteger.reverseGet(5));


An Optional is an optic that allows to see into a structure and getting, setting like a Lens an optional find a value like a Prism.

Optional<Employee, Address> addressOptional = Optional.of(
  Employee::withAddress, employee -> Option.of(employee::getAddress)

Address madrid = new Address("Madrid");
Employee pepe = new Employee("pepe", null);

assertEquals(Option.none(), addressOptional.getOption(pepe));
assertEquals(Option.some(madrid), addressOptional.getOption(addressOptional.set(pepe, madrid)));


Optional Prism Lens Iso
Optional Optional Optional Optional Optional
Prism Optional Prism Optional Prism
Lens Optional Optional Lens Lens
Iso Optional Prism Lens Iso


This class helps to create readable equals methods. An example:

public boolean equals(Object obj) {
  return Equal.<Data>of()
    .applyTo(this, obj);


purefun is released under MIT license

Get A Weekly Email With Trending Projects For These Topics
No Spam. Unsubscribe easily at any time.
java (30,656
functional-programming (464
stream (231
monad (59
experimental (44
memoization (25
monads (25
zio (24

Find Open Source By Browsing 7,000 Topics Across 59 Categories