【问题标题】:How to reference a generic parameter recursively?如何递归引用泛型参数?
【发布时间】:2018-01-02 09:12:17
【问题描述】:

我已经解决了一个 Y 组合器问题。刚才发现不能递归引用泛型参数。

Y = λf.(λx.f (x x)) (λx.f (x x))

例如:

IntUnaryOperator fact = Y(rec -> n -> n == 0 ? 1 : n * rec.applyAsInt(n - 1));

IntUnaryOperator Y(Function<IntUnaryOperator, IntUnaryOperator> f) {
    return g(g -> f.apply(x -> g.apply(g).applyAsInt(x)));
}

IntUnaryOperator g(G g) {
    return g.apply(g);
}

//        v--- I want to remove the middle-interface `G`
interface G extends Function<G, IntUnaryOperator> {/**/}

:如何在方法g上使用泛型参数来避免引入额外的接口G,并且泛型参数应该避免UNCHECKED的警告?

提前致谢。

【问题讨论】:

  • 我很确定这是不可能的。 Java 没有提供一种方法来要求给定的泛型参数是功能接口 AFAIK。

标签: java generics functional-programming java-8


【解决方案1】:

你可以用递归类型定义声明一个泛型方法

<G extends Function<G, IntUnaryOperator>> IntUnaryOperator g(G g) {
    return g.apply(g);
}

不行的是,使用 lambda 表达式调用此方法,将 lambda 表达式分配给 GThe specification

15.27.3。 Lambda 表达式的类型

如果 T 是函数式接口类型(第 9.8 节),则 lambda 表达式在赋值上下文、调用上下文或转换上下文中与目标类型 T 兼容……

G不是函数式接口,而是类型参数,这里无法推断G的实际接口类型。

当您将实际接口 G 用于 lambda 表达式时,这仍然有效:

IntUnaryOperator Y(Function<IntUnaryOperator, IntUnaryOperator> f) {
    return g((G)g -> f.apply(x -> g.apply(g).applyAsInt(x)));
}

// renamed the type parameter from G to F to avoid confusion
<F extends Function<F, IntUnaryOperator>> IntUnaryOperator g(F f) {
    return f.apply(f);
}

// can't get rid of this interface
interface G extends Function<G, IntUnaryOperator> {/**/}

IntUnaryOperator fact = Y(rec -> n -> n == 0 ? 1 : n * rec.applyAsInt(n - 1));

IntUnaryOperator Y(Function<IntUnaryOperator, IntUnaryOperator> f) {
    return this.<G>g(g -> f.apply(x -> g.apply(g).applyAsInt(x)));
}

// renamed the type parameter from G to F to avoid confusion
<F extends Function<F, IntUnaryOperator>> IntUnaryOperator g(F f) {
    return f.apply(f);
}

// can't get rid of this interface
interface G extends Function<G, IntUnaryOperator> {/**/}

所以g 方法是泛型的,不依赖于接口G,但仍需要将接口用作 lambda 表达式的目标类型。

【讨论】:

  • 是的,我刚刚发现类型变量也可以递归引用。问题出在 lambda 表达式中。非常感谢先生。例如:g(null) 工作正常,但 g(g -&gt; null) 不能工作。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2020-02-06
  • 2017-11-18
  • 1970-01-01
  • 1970-01-01
  • 2012-08-15
  • 2016-05-28
  • 1970-01-01
相关资源
最近更新 更多