首页 > 解决方案 > 如何使用柯里化实现泛型类型

问题描述

鉴于这种通用柯里化的实现:

public static <T, U, R> Function<T, Function<U, R>> curry(BiFunction<T, U, R> biFunction) {
        return t -> u -> biFunction.apply(t, u);
    }

 public static int add(int x, int y) {
        return x + y;
    }

并这样称呼它:

Function<Integer, Function<Integer, Integer>> addGen = curry(Curry::add);
System.out.println(addGen.apply(10).apply(20));

如何扩展此 curry() 函数以获取更多参数?喜欢

addGen.apply(10).apply(20).apply(30)....apply(100)

任何帮助表示赞赏。

谢谢。

标签: javagenericscurrying

解决方案


没有干净或内置的方法可以做到这一点。

您可以通过定义具有非常狂野的返回类型的方法来做到这一点:

Function<Integer, Function<Integer, Function<Integer, Function<Integer, Function<Integer, Function<Integer, Function<Integer, Function<Integer, Function<Integer, Function<Integer, Integer>>>>>>>>>>

我希望它说明了试图笼统地解决这个问题是冗长的、混乱的、难以阅读的......(我什至不确定我在Function这里得到了正确的 s 数量)。

接受 10 个参数的函数——curried 或 uncurried——真的没那么有用。你甚至不能用像 Haskell 这样的适当的函数式语言清楚地表达这一点。

然后,当您需要 10 以外的数字时会发生什么。这只是一团糟。

不要尝试使用柯里化。只需将您的 10 个(或多个)参数视为一个列表,并减少它们:

Stream.of(a1, ..., a10).reduce(Integer::sum)

简单、干净、标准。

可以想象,您可以定义如下接口:

interface StoppableFunction<T> extends Function<T, StoppableFunction<T>> {
  T stop();
}

并像这样实现它:

class Impl<T> implements StoppableFunction<T> {
  Impl(T result, BinaryFunction<T> fn) {
    this.result = result; // field defs omitted
    this.fn = fn;
  }

  public Impl<T> apply(T arg) {
    return new Impl<>(fn.apply(result, arg), fn);
  }

  T stop() {
    return result;
  }
}

然后你可以这样调用:

new Impl<>(0, Integer::sum).apply(10).apply(20)....apply(100).stop()

但这并不是真正的咖喱。


推荐阅读