在 Monad 中将 java.util.Function 转换为非 Lambda 表达式 1 示例取自 维基百科

Converting java.util.Function to non-Lambda expression one in Monad example taken from Wikipedia

提问人:toowren 提问时间:9/20/2023 更新时间:9/27/2023 访问量:38

问:

有一个非常简单的 Monad 示例,用 Java 编写,取自维基百科文章。

import java.util.function.Function;

interface Monad<T> {
    <U> Monad<U> bind(Function<T, Monad<U>> f);
}

class Maybe<T> implements Monad<T> {

    private final T val;

    public Maybe(T val) {
        this.val = val;
    }

    public T getVal() {
        return val;
    }

    @Override
    public <U> Monad<U> bind(Function<T, Monad<U>> f) {
        if (val == null)
            return new Maybe<U>(null);
        return f.apply(val);
    }
}

public class MonadApp {
    public static void main(String[] args) {
        Maybe<Integer> x = new Maybe<>(5);
        Monad<Integer> y = x
                .bind(v -> new Maybe<>(v + 1))
                .bind(v -> new Maybe<>(v * 2));

        System.out.println( ((Maybe<Integer>)y).getVal() );
    }
}

出于学术目的,我正在尝试在没有 lambda 表达式的情况下重写旧的 Java 1.7 版本。

我的代码如下所示

import java.util.function.Function;

class MonadFunction implements Function<T, Monad<U>>{
    
    Monad<U> apply(T val) { return Monad<U>(val + 1); }
    
}

interface Monad<T> {
    <U> Monad<U> bind(Function<T, Monad<U>> f);
}

class Maybe<T> implements Monad<T> {

    private final T val;

    public Maybe(T val) {
        this.val = val;
    }

    public T getVal() {
        return val;
    }

    @Override
    public <U> Monad<U> bind(Function<T, Monad<U>> f) {
        if (val == null)
            return new Maybe<U>(null);
        return f.apply(val);
    }
}

public class MonadApp {
    public static void main(String[] args) {
        Maybe<Integer> x = new Maybe<>(5);
 
        Monad<Integer> y = x.bind(new MonadFunction())
        
        System.out.println( ((Maybe<Integer>)y).getVal() );
    }
}

我用

class MonadFunction implements Function<T, Monad<U>>{

    Monad<U> apply(T val) { return Monad<U>(val + 1); }

}

但是,脱机和联机编译器都会返回错误和/MonadApp.java:3: error: cannot find symbol class MonadFunction implements Function<T, Monad<U>>{symbol: class U /MonadApp.java:5: error: cannot find symbol Monad<U> apply(T val) { return Monad<U>(val + 1); }

问题是我做错了什么?

Java 函数 lambda monads

评论

0赞 rzwitserloot 9/20/2023
一吨。 在 Java 1.7 中根本不存在,所以你不能使用它(当然,你可以自己制作)。synax 甚至不是合法的 java。你是说也许吗?这仍然不起作用 - val 的类型是 ,可以是任何东西。“任何东西”都不能保证与“+1”有有意义的交互。因此,该代码没有任何语义意义。Functionreturn Monad<U>(val + 1);return new Monad<U>(val + 1);T
0赞 Louis Wasserman 9/20/2023
实现 Monads 比这更难,但实际上,您不想创建一个名为 .真的,只需创建自己的界面并保持其他所有内容不变即可。MonadFunctionFunction
0赞 toowren 9/20/2023
干杯。就目前而言,我不是在寻找 val + 1 或任何其他操作,而是一种使 lambda 表达式成为自由代码的方法。例如,至少在 1.8 上工作正常,非常确定这是一个泛型类型问题。class FunctionWithoutLambda implements Function<String, Integer> { FunctionWithoutLambda() { } Integer apply(String string_) { return string_.length(); } }
0赞 Tim Moore 9/20/2023
该类未定义 .请澄清一下:您是否真的需要它来与 Java 1.7 一起使用,或者您只是想让它在不使用 lambda 的情况下在 1.8 中工作?MonadFunctionT

答:

0赞 Tim Moore 9/22/2023 #1

如果您只需要在不使用 lambda 的情况下在 Java 8 中完成这项工作,您还可以创建一个实现以下内容的类:Function

class Adder implements Function<Integer, Monad<Integer>> {
    private final int num;

    Adder(int num) {
        this.num = num;
    }

    @Override
    public Monad<Integer> apply(Integer integer) {
        return new Maybe<>(integer + num);
    }
}

public class MonadApp {
    public static void main(String[] args) {
        Maybe<Integer> x = new Maybe<>(5);
        Monad<Integer> y = x
                .bind(new Adder(1))
                .bind(new Adder(2));

        System.out.println( ((Maybe<Integer>)y).getVal() );
    }
}

在这种情况下,和 的定义保持不变。MonadMaybe

如果它确实需要与 Java 7 一起使用,则不可用,但您可以轻松地自己定义一个相同的接口:java.util.function.Function

interface Function<T, U> {
    U apply(T value);
}

如果您使用此接口而不是 ,这将适用于 Java 7 和 Java 8,甚至适用于 lambda。java.util.function.Function

0赞 jon hanson 9/26/2023 #2

由于以下几个原因,您的方法存在缺陷:

  1. 您可以在 Java 中实现 monadic 类型,但您无法有效地表达您的类型是 的事实,因为 bind 方法的返回类型需要是 M(M 是实际的 monad 类型),而不是 .由于缺少更高种类的类型,这不可能在 Java 中表达。您也无法捕获 monad 类型需要具有静态方法(有时称为 或 )的事实。MonadMonad<U>purereturnunit
  2. 您的类型不是有效的 Java,因为未声明泛型类型参数 T 和 U(类声明应以 )。即使您解决了这个问题,您仍然会遇到上述问题。MonadFunctionclass MonadFunction<T, U>

但是,一旦您抛弃了类型,您就可以很容易地表达您的类,而无需求助于 Lambda 函数:MaybeMonad

class Maybe<T> {

    private final T val;

    public Maybe(T val) {
        this.val = val;
    }

    public T getVal() {
        return val;
    }

    public <U> Maybe<U> bind(Function<T, Maybe<U>> f) {
        if (val == null)
            return new Maybe<U>(null);
        else
            return f.apply(val);
    }
}

public class MonadApp {
    public static void main(String[] args) {
        Maybe<Integer> x = new Maybe<>(5);

        Maybe<String> y = x.bind(new Function<Integer, Maybe<String>>() {
            @Override
            public Maybe<String> apply(Integer i) {
                return i == 0 ? new Maybe<>(null) : new Maybe<>(i.toString());
            }
        });

        System.out.println(y.getVal());
    }
}