构建monad时Java泛型的问题

构建monad时Java泛型的问题,java,generics,functional-programming,monads,Java,Generics,Functional Programming,Monads,为了创建一个函数式monad,我一直在玩Java代码,但是我在使用泛型时被打动了,如果我不强制转换对象,Java编译器会给我一个编译错误(尽管泛型可以解决这个问题!) 这是用法: //COMPILATION ERROR! It requires a cast to String String message = If.of("Hi", s->s!=null).apply(s->s+" guys!").get(); 允许: 这是我的单子: import java.util.funct

为了创建一个函数式monad,我一直在玩Java代码,但是我在使用泛型时被打动了,如果我不强制转换对象,Java编译器会给我一个编译错误(尽管泛型可以解决这个问题!)

这是用法:

//COMPILATION ERROR! It requires a cast to String
String message = If.of("Hi", s->s!=null).apply(s->s+" guys!").get();
允许:

这是我的单子:

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

}
import java.util.function.function;
导入java.util.function.Predicate;
公共类如果{
私人T;
私有谓词;
私有If(T,谓词){
t=t;
this.predicate=谓词;
}
公共静态If of(T,谓词){
返回新的If(t,谓词);
}
公共(如果适用)(功能){
if(谓词!=null&&predicate.test(t)){
返回新的If(function.apply(t),null);
}
返回If.of(this.t,null);
}
公共部门得不到{
返回t;
}
}

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

public static<T> If of(T t, Predicate predicate) {
那么您的
签名可以是:

public static<T> If<T> of(T t, Predicate<T> predicate) {
公共静态If of(T,谓词){

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

public static<T> If<T> of(T t, Predicate<? super T> predicate) {

publicstaticif of(T,PredicateAndy Turner的回答解释了当前代码无法编译的直接原因,但您的monad似乎有一个更根本的问题——它不是很有用

根据您的说法,如果条件为true,则对
apply
的第一次调用应返回包装在monad中的转换对象,如果条件为false,则应返回包装在monad中的原始对象。但是,由于您将
null
作为这两种情况的条件,因此对
apply
的任何后续调用都将导致要到达的第二个
返回
,因此总是返回第一次调用
应用
的结果

事实上,既不能返回原始对象,也不能返回转换后的对象(无论如何,这不是一种有用且类型安全的方式)。要安全地进行键入,您需要一个
(假设存在这样的类型).但是要从
中提取值,仍然需要一个if语句,这与
if
类的目的背道而驰


显然,这只是一个练习编写monad的练习。在这种情况下,我建议您选择另一个monad来实现,例如
。我也建议您先看看这个。

公共静态If of(T,谓词谓词){
--返回类型是原始的。我想它应该是
谓词
左右。如果包含编译器的错误消息,将使用原始类型的问题放在一边,那会很有帮助。这个monad应该做什么?If.of(1,x->x>2)。apply(Integer::toString).get()会做什么
return?换句话说,当条件为false时会发生什么?您是否期望
null
?如果条件为false,它将返回此值。例如,它就像mapIf,它将存在于可选的monad中。它仅在验证谓词时应用转换。并且,否,
get
无法返回原始对象或转换对象,因为它们可能是不同的类型。原始对象的类型是
T
,而转换对象的类型是
R
。您可以在这里使用
单子,但如果
的话,这种类型会破坏
的目的,对吗?因为您仍然必须检查返回的是哪一个ed.你想用这个
If
monad实现什么?如果这只是monad的一个练习,那么还有很多其他monad可以编写。非常有趣的建议,我已经尝试过了,但在apply()的最后一次返回中方法它给了我编译错误,因为它返回的是If而不是If。如何解决这个问题?谢谢@Sweeper not null而是this。这意味着返回monad本身。@AlexMawashi哦,对了。在这种情况下,你根本不需要
R
:你必须返回
If
public static<T> If<T> of(T t, Predicate<T> predicate) {
public static<T> If<T> of(T t, Predicate<? super T> predicate) {
public <R> If<R> apply(Function<? super T, ? extends R> function) {