为什么这个函数的 pointfree 版本看起来像这样?

发布于 2024-09-07 07:21:16 字数 388 浏览 5 评论 0原文

我一直在使用 Haskell,包括练习以无点形式编写函数。这是一个示例函数:

dotProduct :: (Num a) => [a] -> [a] -> a
dotProduct xs ys = sum (zipWith (*) xs ys)

我想以无点形式编写这个函数。这是我在其他地方找到的一个例子:

dotProduct = (sum .) . zipWith (*)

但是,我不明白为什么无点形式看起来像 (sum .) 。 zipWith (*) 而不是 sum 。 zipWith (*).为什么 sum 放在括号中并且有 2 个复合运算符?

I've been playing around with Haskell a fair bit, including practising writing functions in point-free form. Here is an example function:

dotProduct :: (Num a) => [a] -> [a] -> a
dotProduct xs ys = sum (zipWith (*) xs ys)

I would like to write this function in point-free form. Here is an example I found elsewhere:

dotProduct = (sum .) . zipWith (*)

However, I don't understand why the point-free form looks like (sum .) . zipWith (*) instead of sum . zipWith (*). Why is sum in brackets and have 2 composition operators?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

一紙繁鸢 2024-09-14 07:21:21

KennyTM 的答案非常好,但我仍然想提供另一种观点:

dotProduct = (.) (.) (.) sum (zipWith (*))
  • (.) f g 在给定的 g 的结果上应用 f参数
  • (.) (.) (.) f gf 应用于给定两个参数 (.) (.) g 的结果
  • 。 ) ((.) (.) (.)) f g 在给定三个参数的 g 的结果上应用 f
  • ...
  • 可以做 ( .~) = (.) (.) (.), (.~~) = (.) (.) (.~), (.~~~ ) = (.) (.) (.~~) 现在 let foo abcd = [1..5]; (.~~~) sum foo 0 0 0 0 结果为 15
    • 但我不会这么做。它可能会使代码不可读。只要满分就好。
  • Conal 的 TypeCompose 提供了 (.) 的同义词,称为 result。也许这个名字更有助于理解正在发生的事情。
      如果导入相关实例(import Control.Applicative 就可以),

    • fmap 也可以代替 (.),但它的类型更笼统,因此可能更令人困惑。
  • Conal 的“融合”概念(不要与“融合”的其他用法混淆)是相关的,恕我直言,它提供了一种很好的组合函数的方法。更多详细信息,请参阅 Conal 发表的这篇长篇 Google 技术讲座

KennyTM's answer is excellent, but still I'd like to offer another perspective:

dotProduct = (.) (.) (.) sum (zipWith (*))
  • (.) f g applies f on the result of g given one argument
  • (.) (.) (.) f g applies f on the result of g given two arguments
  • (.) (.) ((.) (.) (.)) f g applies f on the result of g given three arguments
  • ...
  • Can do (.~) = (.) (.) (.), (.~~) = (.) (.) (.~), (.~~~) = (.) (.) (.~~) and now let foo a b c d = [1..5]; (.~~~) sum foo 0 0 0 0 results in 15.
    • But I wouldn't do it. It will probably make code unreadable. Just be point-full.
  • Conal's TypeCompose provides a synonym for (.) called result. Perhaps this name is more helpful for understanding what's going on.
    • fmap also works instead of (.), if importing the relevant instances (import Control.Applicative would do it) but its type is more general and thus perhaps more confusing.
  • Conal's concept of "fusion" (not to be confused with other usages of "fusion") is kind of related and imho offers a nice way to compose functions. More details in this long Google Tech Talk that Conal gave
初熏 2024-09-14 07:21:19
dotProduct xs ys = sum (zipWith (*) xs ys)             -- # definition

dotProduct xs    = \ys -> sum (zipWith (*) xs ys)      -- # f x = g <=> f = \x -> g
                 = \ys -> (sum . (zipWith (*) xs)) ys  -- # f (g x) == (f . g) x
                 = sum . (zipWith (*) xs)              -- # \x -> f x == f
                 = sum . zipWith (*) xs                -- # Precedence rule

dotProduct       = \xs -> sum . zipWith (*) xs         -- # f x = g <=> f = \x -> g
                 = \xs -> (sum .) (zipWith (*) xs)     -- # f * g == (f *) g
                 = \xs -> ((sum .) . zipWith (*)) xs   -- # f (g x) == (f . g) x
                 = (sum .) . zipWith (*)               -- # \x -> f x == f

(sum .) 是一个部分。它被定义为

(sum .) f = sum . f

任何二元运算符都可以这样写,例如map (7 -) [1,2,3] == [7-1, 7-2, 7-3]

dotProduct xs ys = sum (zipWith (*) xs ys)             -- # definition

dotProduct xs    = \ys -> sum (zipWith (*) xs ys)      -- # f x = g <=> f = \x -> g
                 = \ys -> (sum . (zipWith (*) xs)) ys  -- # f (g x) == (f . g) x
                 = sum . (zipWith (*) xs)              -- # \x -> f x == f
                 = sum . zipWith (*) xs                -- # Precedence rule

dotProduct       = \xs -> sum . zipWith (*) xs         -- # f x = g <=> f = \x -> g
                 = \xs -> (sum .) (zipWith (*) xs)     -- # f * g == (f *) g
                 = \xs -> ((sum .) . zipWith (*)) xs   -- # f (g x) == (f . g) x
                 = (sum .) . zipWith (*)               -- # \x -> f x == f

The (sum .) is a section. It is defined as

(sum .) f = sum . f

Any binary operators can be written like this, e.g. map (7 -) [1,2,3] == [7-1, 7-2, 7-3].

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文