构建 monad 时 Java 泛型的问题

Ale*_*shi 2 java generics monads functional-programming

我正在玩 Java 代码以创建一个函数式风格的 monad,但是我在使用泛型时感到震惊,如果我不强制转换我的对象,Java 编译器会给我一个编译错误(尽管泛型可以解决这个问题!)

这是用法:

//COMPILATION ERROR! It requires a cast to String
String message = If.of("Hi", s->s!=null).apply(s->s+" guys!").get();
Run Code Online (Sandbox Code Playgroud)

允许:

这是我的单子:

import java.util.function.Function;
import java.util.function.Predicate;

public class If<T, R> {

  private T t;
  private Predicate predicate;

  private If(T t, Predicate predicate) {
    this.t = t;
    this.predicate = predicate;
  }

  public static<T> If of(T t, Predicate predicate) {
    return new If(t, predicate);
  }

  public If<R,R> apply(Function<T, R> function) {
    if(predicate!=null && predicate.test(t)){
        return new If<R, R>(function.apply(t), null);
    }
    return If.of(this.t, null);
  }

  public T get() {
    return t;
  }

}
Run Code Online (Sandbox Code Playgroud)

And*_*ner 5

直接的问题是该方法的返回类型of是原始的:

public static<T> If of(T t, Predicate predicate) {
Run Code Online (Sandbox Code Playgroud)

你大概需要它是这样的:

public static<T> If<T, Something> of(T t, Predicate<T> predicate) {
Run Code Online (Sandbox Code Playgroud)

我建议你不要真的想把 烘焙RIf's 类型。如果您改为在方法上声明它,则您可以灵活地将apply其设置为您需要的任何类型:

public class If<T> {
  // ...

  public <R> If<R> apply(Function<T, R> function) {
    if(predicate!=null && predicate.test(t)){
      return new If<>(function.apply(t), null);
    }
    return If.of(this.t, null);
  }

  // ...
}
Run Code Online (Sandbox Code Playgroud)

那么你的of签名可以是简单的:

public static<T> If<T> of(T t, Predicate<T> predicate) {
Run Code Online (Sandbox Code Playgroud)

如果您希望 API 更加灵活,请添加通配符:

public static<T> If<T> of(T t, Predicate<? super T> predicate) {
Run Code Online (Sandbox Code Playgroud)

public <R> If<R> apply(Function<? super T, ? extends R> function) {
Run Code Online (Sandbox Code Playgroud)