【问题标题】:How do curried functions work in Haskell?柯里化函数如何在 Haskell 中工作?
【发布时间】:2016-12-15 04:13:53
【问题描述】:

我正在学习 Haskell。我知道 Haskell 中的任何函数都只能接受一个参数。所以,如果你看到一个函数max 2 4;它实际上是(max 2) 4。他们说的是第一个2 应用于(作为参数)max,它返回一个函数,它将4 作为参数。我不明白的是当 2 应用于最大值时会发生什么?它返回一个名为(max 2)的函数是什么意思?

让我再举一个例子,让我的问题更清楚。取这个函数:multiply x y x = x*y*z。他们说它实际上是这样评估的:((multiply x) y) z。现在我给出这个输入:multiply 2*4*5 这是如何评估的?

multiply 2

返回 (multiply 2) 并应用 4 作为参数:

(multiply 2) 4

现在返回的是什么——((multiply 2) 4)multiply 8?如果它在这一步乘以 4 和 2,Haskell 怎么知道它必须这样做(因为函数只能乘以 3 个参数)?

【问题讨论】:

  • 当您调用(multiply 2) 4 时,结果值为(multiply 2) 4,或更明确地为\x -> multiply 2 4 x。在这个阶段不会进行额外的评估,因为它不能。一旦函数调用完全饱和(并且需要它的值,因为 Haskell 是惰性的,但这与柯里化无关),然后才会应用该函数。
  • 当你有“multiply 2*4*5”时,你的意思是“multiply 2 4 5”吗?
  • Haskell 报告没有具体说明如果给miltiply 两个参数会发生什么。它可能很好地用两个参数做一些减少,但我不知道有任何实现(完整的 Haskell)可以做到这一点。
  • 另外,Haskell 不是懒惰的,它是非严格的。
  • 如果你熟悉 JavaScript:max = function(x) { return function(y) { return x <= y ? y : x; }; };,那么 max(2) 是一个匿名函数,它的闭包包含一个值 2max(2)(4)4。在 Haskell 中也是如此,尽管出于性能原因,当您完全应用函数时,GHC 不会分配闭包。

标签: haskell


【解决方案1】:

只要从数学上思考一下:假设有一个带有两个变量的函数:f(x, y)。修复 x=2 会给你一个带有一个变量的新函数:g(y)=f(2, y)

如果 f(x, y) = max(x, y) 给出 x 和 y 的最大值,g(y) = f(2, y) = max(2, y) 给出 2 和 y 的最大值。

对于f(x, y, z) = x * y * zg(y, z) = f(2, y, z) = 2 * y * zh(z) = g(4, z) = f(2, 4, z) = 2 * 4 * z

您还可以将 x=2 和 z=4 固定为 p(y) = f(2, y, 4)。在 Haskell 中是

\y -> multiply 2 y 4

对于实现,Haskell 实际上不会将 2 和 4 相乘,因为它是惰性求值的。也就是说,它不会计算一个值,直到它必须这样做。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-04-22
    • 2012-09-21
    • 2017-05-16
    • 2011-10-02
    • 2018-04-18
    • 2016-01-01
    • 1970-01-01
    相关资源
    最近更新 更多