【问题标题】:Implementing Monads in Java 8在 Java 8 中实现 Monad
【发布时间】:2019-05-30 06:34:59
【问题描述】:

我正在尝试在this article 之后在 Java 8 中实现 Monad 接口,但是我遇到了以下编译错误


发现 2 个错误:

  • 文件:FunctorsMonads.java [行:36]

    错误:FOptional 不是抽象的,不会覆盖 Monad 中的抽象方法 flatMap(java.util.function.Function>)

  • 文件:FunctorsMonads.java [行:50]

    错误:名称冲突:FOptional 中的 flatMap(java.util.function.Function>) 和 Monad 中的 flatMap(java.util.function.Function) 具有相同的擦除,但都不会覆盖另一个


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

编辑:
我在 main 方法中添加了以下几行作为实现正确性的试金石:
FOptional<Integer> num2 = str.flatMap(FunctorsMonads::tryParse); System.out.println(num2);

【问题讨论】:

  • 干杯 @Nikolas 改进了我的原始格式并使问题更易于阅读。

标签: java generics java-8 functional-programming monads


【解决方案1】:

您不能在 Java 中实现完全类型安全的 Monad 接口。 flatmap 的正确签名应该是 &lt;R&gt; M&lt;R&gt; flatMap(Function&lt;T, M&lt;R&gt;&gt; f),但这在 Java 中是不可表达的。这个M&lt;R&gt; 表达式称为higher-kinded type

【讨论】:

    【解决方案2】:

    实现的方法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);
    }
    

    它们都定义了返回新泛型类型的方法:MonadMFunctorF,并使用新引入的泛型类型 R

    【讨论】:

    • 只是&lt;R&gt; M flatMap(Function&lt;T, FOptional&lt;R&gt;&gt; f); 在接口Monad 的合约中引入FOptional,此后由FOptional 实现。这种方法不应该与实现而不是接口一起存在吗?
    • 您的答案似乎是使此代码编译的唯一可能方法。这向我表明@MikeFHay 的答案目前是正确的。
    猜你喜欢
    • 1970-01-01
    • 2014-01-10
    • 1970-01-01
    • 1970-01-01
    • 2017-10-10
    • 2017-05-20
    • 2015-11-10
    • 1970-01-01
    相关资源
    最近更新 更多