java - 这是 Java 中柯里化(Currying)的有效示例吗

标签 java functional-programming currying

我试图理解 Java 中的柯里化(Currying)并创建了以下简单示例。这是柯里化(Currying)的有效示例还是我错过了重点?

    // Before
    House constructHouse1(Foundation f, Building b) {
        return new House(f, b);
    }

    // After
    House constructHouse2(Foundation f, Building b) {
        return constructHouseWithBuilding(b).apply(f);
    }

    Function<Foundation, House> constructHouseWithBuilding(Building b) {
        return constructHouseWithFoundation(b);
    }

    Function<Foundation, House> constructHouseWithFoundation(Building b) {
        return foundation -> new House(foundation, b);
    }

    // Beans
    class Foundation { }
    class Building { }
    class House {
        Foundation f;
        Building b;
        House(Foundation f, Building b) {
            this.f = f;
            this.b = b;
        }
    }

最佳答案

有点。

通过柯里化(Currying)函数,我们理解一种函数,它不是采用多个参数,而是采用一个参数并返回另一个函数,直到返回所有参数。所以代替:

BiFunction<Foundation, Building, House> constructHouse = ...;

你会有

Function<Foundation, Function<Building, House>> curriedConstructHouse = ...;

我们在这里讨论的是概念,而不是特定的实现,因此我们可以考虑手动柯里化(Currying)它们。

House constructHouse(Foundation f, Building b) {
    return new House(f, b);
}

Function<Foundation, House> constructHouseWithBuilding(Building b) {
    return f -> constructHouse(f, b);
}

因为类型很重要,Foundation -> Building -> HouseBuilding -> Foundation -> House 不同。如果我们谈论柯里化(Currying),它们是具有不同签名的两个函数的柯里化(Currying)变体:(Foundation, Building) -> House(Building, Foundation) -> House

如果您想将多个参数应用于一个函数,而该函数具有更多要应用的参数(无论它们在哪里),我们通常会讨论部分应用。看看柯里化(Currying)通常是如何理解的,您可以将其视为部分应用的特殊情况,其中您始终部分应用剩余参数列表中的第一个参数,并且我们一次部分应用所有剩余参数。

因此,我认为这是部分应用:

House constructHouse(Foundation f, Building b) {
    return new House(f, b);
}

Function<Building, House> constructHouseWithFoundation(Foundation f) {
    return b -> constructHouse(f, b);
}

也许更多的例子可以澄清差异(让我们假设 vavs 或具有超过 2 个参数的函数的东西,但此代码是伪代码):

A a; B c; C c; // arguments to pass
               // a1, b2, c1 will be used as arguments in lambdas to avoid confusion

// uncurried
// (A, B, C) -> D
Function3<A, B, C , D> f;
f.apply(a, b, c); // returns D

// curried
// A -> B -> C -> D
Function1<A, Function1<B, Function1<C, D>>> curried = f.curried(); // curried() is available in Vavr's functions
curried.apply(a).apply(b).apply(c); // returns D

// partially applied B
// (A, C) -> D
Function2<A, C, D> partially1 = (a1, c1) -> f(a1, b, c1); // there is no syntactic sugar for this in Java that I am aware of

// partially applied A and C
// B -> D
Function1<B, D> partially2 = (b1) -> f(a, b1, c); 

// neither currying nor partial application
Function3<C, A, B, D> reordered = (c1, a1, b1) -> f(a1, b1, c1);

因此,我可以将您的 constructHouseWithFoundation 视为柯里化(Currying)函数,并将 constructHouse2 视为 constructHouseWithFoundation 的非柯里化(Currying)版本。

关于java - 这是 Java 中柯里化(Currying)的有效示例吗,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/65337857/

相关文章:

java - 如何正确混合泛型和继承以获得预期的结果?

programming-languages - 部分评估和柯里化(Currying)

functional-programming - Haskell 函数定义语法

java - 如何在 p :dataGrid using p:graphicImage 中显示图像

java - 有没有办法在使用 GCM 接收推送通知时调试应用程序?

performance - Scala 函数式编程比传统编码慢吗?

javascript - compose 函数如何处理多个参数?

Haskell Monad 绑定(bind)运算符混淆

java - 扫描仪返回错误的 int 值

unit-testing - 单元测试 elixir 功能正常