`sum (replicate 5 (max 6.7 8.9))` 和 `(sum . replicate 5 . max 6.7) 8.9` 如何得到相同的结果?

How does `sum (replicate 5 (max 6.7 8.9))` and `(sum . replicate 5 . max 6.7) 8.9` get the same result?

使用函数组合重写 (sum . replicate 5 . max 6.7) 8.9。我们有

(sum . replicate 5 . max 6.7) 8.9

我理解 (sum . replicate 5 . max 6.7) 部分。但是它如何处理 8.9?

编辑评论:原来,6.7中的.不是函数组合运算符,而是小数点!

max 6.7Double 和 returns 取 Doublereplicate 5Double 并生成 [Double]sum 采用 [Double] 和 returns 类型 Double。 (在类型推断之后。)

. 只是将所有这些函数链接在一起,所以你剩下一个 Double -> Double 类型的函数。然后将 8.9 传递给该函数。

如果写f . g,这基本上就是\x -> f (g x)的简写。由于 (.) 运算符是右结合的,因此您的函数等效于:

=    (sum . replicate 5 . max 6.7) 8.9
--------------------------------------
   (sum . (replicate 5 . max 6.7)) 8.9

和:

=                    (sum . (replicate 5 . max 6.7)) 8.9
--------------------------------------------------------
   (\x -> sum ((\y -> (replicate 5 (max 6.7 y))) x)) 8.9

所以现在如果我们执行评估,我们会看到:

=  (\x -> sum ((\y -> (replicate 5 (max 6.7 y))) x)) 8.9
--------------------------------------------------------
             sum ((\y -> (replicate 5 (max 6.7 y))) 8.9)

和:

=  sum ((\y -> (replicate 5 (max 6.7 y))) 8.9)
----------------------------------------------
               sum (replicate 5 (max 6.7 8.9))

因此函数组合首先将 8.9 作为 max 的第二个参数,然后将所有其他函数应用于某种从右到左的链中的结果。

如果您了解 (sum . replicate 5 . max 6.7) 部分,那么您就会知道它 returns 是一个函数,它对最大数 6.7 和重复 5 次的给定数求和。这个新函数的类型是 Float -> Float.

所以接下来我们将 8.9 应用到这个函数,我们得到最终值。我们可以用更直观的方式来写:

mySum :: Float -> Float
mySum = sum . replicate 5 . max 6.7

result :: Float
result = mySum 8.9

Haskell 中的函数已柯里化。柯里化函数,否则采用两个参数值,您只能使用一个参数值。

f = max 2
f 3

3

当你写 max 2 3 时,它实际上被翻译成带有参数 3 的 (max 2),(max 2) 3 是 Haskell 正在做的事情。

这有助于无点代码。您不必指定函数或函数组合的最终参数,但在调用函数或函数组合时必须提供它。