【问题标题】:Haskell - How does this average function work?Haskell - 这个平均函数是如何工作的?
【发布时间】:2020-08-23 21:52:17
【问题描述】:

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

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

这是如何工作的?我查看了div . sum 产生的函数:

(div . sum) :: (Integral a, Foldable t) => t a -> a -> a

我明白这一点,但我不知道 &lt;*&gt; length 是如何工作的。

【问题讨论】:

    标签: haskell average applicative function-composition pointfree


    【解决方案1】:

    &lt;*&gt; :: Applicative f =&gt; f (a -&gt; b) -&gt; f a -&gt; f b 是在Applicative 结构上工作的顺序应用程序 函数。对于一个函数,这是implemented as [src]

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

    所以f &lt;*&gt; g\x -&gt; f x (g x) 的缩写。因此,这意味着在 avg 的情况下:

    avg = div . sum <*> length
    

    相当于:

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

    因此等价于:

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

    所以它将sum xlength x 分开。

    【讨论】:

    • 捎带这个答案,帮助我使用 &lt;*&gt; 的 ab(uses) 函数的一件事是像 div &lt;$&gt; sum &lt;*&gt; length 一样阅读它。如果你熟悉 f &lt;$&gt; x &lt;*&gt; y &lt;*&gt; z ... 成语,你可以将函数 case 理解为“将x 应用于f 的第一个参数,y 应用于第二个参数,等等。
    【解决方案2】:

    我不喜欢这种特殊的免点技巧。它使用Applicative (a-&gt;) 实例作为“扇出”,将参数传递给两个单独的函数。本质上这两个函数是sumlength,然后将结果通过div 组合回来,这可以用箭头组合器很好地表达(虽然有点冗长,因为箭头在 Haskell 的默认设置中并没有真正发挥作用咖喱风格):

    import Control.Arrow
    
    avg = uncurry div . (sum &&& length)
    

    在应用技巧中,您将组合函数合并到第一个参数共享函数中。所以在这种情况下div . sum,然后将另一个函数lengthresult 传递给第一个函数的第二个参数。

    你也可以使用

    avg = liftA2 div sum length
    

    它也使用Applicative 实例。

    【讨论】:

    • 对!实际上我一开始是这样想的,但是在阅读最后的答案时不知何故犯了一个想法错误,整个事情仍然有两个论点。
    猜你喜欢
    • 2014-07-20
    • 1970-01-01
    • 1970-01-01
    • 2018-07-17
    • 2016-02-22
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多