7

I am trying to implement a Monad interface in Java 8 following this article however I've got the following compiling errors


2 errors found:

  • File:FunctorsMonads.java [line: 36]

    Error: FOptional is not abstract and does not override abstract method flatMap(java.util.function.Function>) in Monad

  • File:FunctorsMonads.java [line: 50]

    Error: name clash: flatMap(java.util.function.Function>) in FOptional and flatMap(java.util.function.Function) in Monad have the same erasure, yet neither overrides the other


The Functor interface works just fine. Any help is much appreciated.

Here is the code:

import java.util.function.Function;

public class FunctorsMonads {

  public static void main(String[] args) {
    System.out.println(tryParse("47"));
    System.out.println(tryParse("a"));

    FOptional<String> str = FOptional.of("47");
    System.out.println(str);
    FOptional<FOptional<Integer>> num = str.map(FunctorsMonads::tryParse);
    System.out.println(num);
    FOptional<Integer> num2 = str.flatMap(FunctorsMonads::tryParse);
    System.out.println(num2);
  }

  static FOptional<Integer> tryParse(String s){
    try {
      final int i = Integer.parseInt(s);
      return FOptional.of(i);
    } catch (NumberFormatException e) {
      return FOptional.empty();
    }
  }
}

interface Functor<T, F extends Functor<?, ?>> {
  <R> F map(Function<T, R> f);
}

interface Monad<T, M extends Monad<?, ?>> extends Functor<T, M> {
  M flatMap(Function<T, M> f);
}

//class FOptional<T> implements Functor<T, FOptional<?>>
class FOptional<T> implements Monad<T, FOptional<?>> {
  private final T valueOrNull;

  private FOptional(T valueOrNull) {
    this.valueOrNull = valueOrNull;
  }

  public <R> FOptional<R> map(Function<T, R> f) {
    if (valueOrNull == null)
      return empty();
    else
      return of(f.apply(valueOrNull));
  }

  public <R> FOptional<R> flatMap(Function<T, FOptional<R>> f) {
    if (valueOrNull == null)
      return empty();
    else
      return f.apply(valueOrNull);
  }

  public static <T> FOptional<T> of(T a) {
    return new FOptional<T>(a);
  }

  public static <T> FOptional<T> empty() {
    return new FOptional<T>(null);
  }

  @Override
  public String toString() {
    return getClass().getName() + "<" + valueOrNull + ">";
  }
}

Edit:
I have added the following lines in the main method as a litmus test of the implementation's correctness:
FOptional<Integer> num2 = str.flatMap(FunctorsMonads::tryParse); System.out.println(num2);

1
  • Cheers @Nikolas for improving my original formatting and making the question easier to read. Commented Jan 4, 2019 at 0:42

2 Answers 2

6

You cannot implement a fully type-safe Monad interface in Java. The correct signature for flatmap would be something like <R> M<R> flatMap(Function<T, M<R>> f), but this is not expressible in Java. This M<R> expression is called a higher-kinded type.

Sign up to request clarification or add additional context in comments.

Comments

1

The implemented method FOptional::flatMap doesn't match the definition in the interface Monad.

All you need is to amend the interface Monad itself:

interface Monad<T, M extends Monad<?, ?>> extends Functor<T, M> {

    <R> M flatMap(Function<T, FOptional<R>> f);
}

Moreover, as far as I understand from the functionality, both interfaces shall be designed with the same spirit. Compare the new interface with the Functor interface:

interface Functor<T, F extends Functor<?, ?>> {

    <R> F map(Function<T, R> f);
}

Both of them define methods that return the new generic type: Monad with M and Functor with F and use a newly introduced generic type R.

2 Comments

Just that <R> M flatMap(Function<T, FOptional<R>> f); brings in FOptional within the interface Monad's contracts which thereafter is implemented by FOptional. Shouldn't such method reside with implementations instead of interfaces?
Your answer seems to be the only possible way of making this code to compile. This shows me that @MikeFHay 's answer is the right one for the time being.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.