Реализация монад в Java 8 - PullRequest
       20

Реализация монад в Java 8

0 голосов
/ 03 января 2019

Я пытаюсь реализовать интерфейс Monad в Java 8, следуя этой статье , однако я получил следующие ошибки компиляции


2 найдено ошибок:

  • Файл: FunctorsMonads.java [строка: 36]

    Ошибка: FOptional не является абстрактным и не переопределяет абстрактный метод flatMap (java.util.function.Function>) вMonad

  • Файл: FunctorsMonads.java [строка: 50]

    Ошибка: конфликт имен: flatMap (java.util.function.Function>) в FOptional и flatMap (java.util.function.Function) в Monad имеют одинаковое стирание, но ни один не переопределяет другие


Интерфейс Functor работаетпросто хорошо.Любая помощь очень ценится.

Вот код:

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 + ">";
  }
}

Редактировать:
Я добавил следующие строки в основной метод в качестве лакмусапроверка правильности реализации:
FOptional<Integer> num2 = str.flatMap(FunctorsMonads::tryParse); System.out.println(num2);

Ответы [ 2 ]

0 голосов
/ 03 января 2019

Вы не можете реализовать полностью безопасный интерфейс Monad в Java. Правильная подпись для flatmap будет выглядеть примерно так: <R> M<R> flatMap(Function<T, M<R>> f), но в Java это невозможно выразить. Это выражение M<R> называется типом высшего рода .

0 голосов
/ 03 января 2019

Реализованный метод FOptional::flatMap не соответствует определению в интерфейсе Monad.

Все, что вам нужно, это изменить сам интерфейс Monad:

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

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

Более того, насколько я понимаю из функциональности, оба интерфейса должны быть спроектированы в одном духе. Сравните новый интерфейс с интерфейсом Functor:

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

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

Оба они определяют методы, которые возвращают новый универсальный тип: Monad с M и Functor с F и используют недавно введенный универсальный тип R.

...