Haskell - 这个平均函数是如何工作的?

Haskell - How does this average function work?

我找到了这个平均函数的实现:

avg :: [Int] -> Int
avg = div . sum <*> length

这是如何工作的?我查看了由于 div . sum:

而产生的函数
(div . sum) :: (Integral a, Foldable t) => t a -> a -> a

我明白了,但我不知道 <*> length 是如何工作的。

<*> :: Applicative f => f (a -> b) -> f a -> f b is the sequential application function that works on an Applicative structure. For a function, this is implemented as [src]:

instance Applicative ((->) r) where
    pure = const
    <b>(<*>) f g x = f x (g x)</b>
    liftA2 q f g x = q (f x) (g x)

所以f <*> g\x -> f x (g x)的缩写。因此,这意味着在 avg:

的情况下
avg = div . sum <*> length

相当于:

avg x = (div . sum) x (length x)

因此相当于:

avg x = div (sum x) (length x)

所以它将 sum x 除以 length x

我不喜欢这个 pointfree-trick。它使用 Applicative (a->) 实例作为“扇出”,将参数传递给两个单独的函数。本质上这两个函数是 sumlength,然后结果由 div 组合回来,这可以用箭头组合器很好地表达(尽管有点冗长,因为箭头不Haskell 的默认 curried 风格并没有真正发挥作用:

import Control.Arrow

avg = uncurry div . (sum &&& length)

在应用技巧中,您将合并功能合并到第一个 argument-sharing 中。所以在这种情况下 div . sum,然后将另一个函数 length 结果 传递给第一个函数的第二个参数。

您也可以使用

avg = liftA2 div sum length

它也使用 Applicative 实例。