简体   繁体   English

Haskell 函数组合 (.) 和函数应用 ($) 习语:正确使用

[英]Haskell function composition (.) and function application ($) idioms: correct use

I have been reading Real World Haskell , and I am nearing the end, but a matter of style has been niggling at me to do with the (.) and ($) operators.我一直在阅读Real World Haskell ,并且快要结束了,但是我一直在苦恼与(.)($)运算符有关的风格问题。

When you write a function that is a composition of other functions you write it like:当你编写一个由其他函数组成的函数时,你可以这样写:

f = g . h

But when you apply something to the end of those functions I write it like this:但是当你在这些函数的末尾应用一些东西时,我是这样写的:

k = a $ b $ c $ value

But the book would write it like this:但是这本书会这样写:

k = a . b . c $ value

Now, to me they look functionally equivalent, they do the exact same thing in my eyes.现在,在我看来,它们在功能上是等效的,在我看来,它们的作用完全相同。 However, the more I look, the more I see people writing their functions in the manner that the book does: compose with (.) first and then only at the end use ($) to append a value to evaluate the lot (nobody does it with many dollar compositions).然而,我看得越多,我就越能看到人们以本书的方式编写函数:首先使用(.)组合,然后仅在最后使用($)附加一个值来评估批次(没有人这样做)它带有许多美元成分)。

Is there a reason for using the books way that is much better than using all ($) symbols?是否有理由使用比使用所有($)符号更好的书籍方式? Or is there some best practice here that I am not getting?或者这里有一些我没有得到的最​​佳实践吗? Or is it superfluous and I shouldn't be worrying about it at all?或者它是多余的,我根本不应该担心它?

I guess I can answer this from authority.我想我可以从权威那里回答这个问题。

Is there a reason for using the books way that is much better than using all ($) symbols?是否有理由使用比使用所有 ($) 符号更好的书籍方式?

There's no special reason.没有什么特别的原因。 Bryan and I both prefer to reduce line noise. Bryan 和我都喜欢减少线路噪音。 . is quieter than $ .$更安静。 As a result, the book uses the f . g . h $ x因此,本书使用了f . g . h $ x f . g . h $ x f . g . h $ x syntax. f . g . h $ x语法。

They are indeed equivalent: Keep in mind that the $ operator does, essentially, nothing.它们确实是等价的:请记住, $运算符本质上什么都不做。 f $ x evaluates to fx . f $ x计算为fx The purpose of $ is its fixity behavior: right-associative and minimal precedence. $的目的是它的固定行为:右结合和最小优先级。 Removing $ and using parentheses for grouping instead of infix precedence, the code snippets look like this:删除$并使用括号进行分组而不是中缀优先级,代码片段如下所示:

k = a (b (c (value)))

and

k = (a . b . c) value

The reason for preferring the .首选. version over the $ version is the same reason for preferring both over the very parenthesized version above: aesthetic appeal.版本优于$版本与上面括号中的版本相比,两者都更受欢迎:审美吸引力。

Although, some might wonder if using infix operators instead of parentheses is based on some subconscious urge to avoid any possible resemblance to Lisp (just kidding... I think?).虽然,有些人可能想知道使用中缀运算符而不是括号是否基于某种潜意识的冲动,以避免与 Lisp 有任何可能的相似之处(开个玩笑……我想?)。

I'd add that in f . g $ x我会在f . g $ x添加它f . g $ x f . g $ x , f . g f . g $ x , f . g f . g is a meaningful syntactic unit. f . g是一个有意义的句法单位。

Meanwhile, in f $ g $ x , f $ g is not a meaningful unit.同时,在f $ g $ xf $ g不是一个有意义的单位。 A chain of $ is arguably more imperative -- first get the result of g of x , then do f to it, then do foo to it, then etc.一个$链可以说是更重要的——首先得到xg的结果,然后对它做f然后对它做foo然后等等。

Meanwhile a chain of .同时一连串的. is arguably more declarative, and in some sense closer to a dataflow centric view -- compose a series of functions, and ultimately apply them to something.可以说更具声明性,并且在某种意义上更接近以数据流为中心的视图——组合一系列函数,并最终将它们应用于某些东西。

For me, I think the answer is (a) the neatness, as Don said ;对我来说,我认为答案是 (a) 正如唐所说的那样整洁; and (b) I find that when I'm editing code, my function may end up in point-free style, and then all I have to do is delete the last $ instead of going back and changing everything. (b) 我发现当我编辑代码时,我的函数可能会以无点样式结束,然后我要做的就是删除最后一个$而不是返回并更改所有内容。 A minor point, certainly, but a nicety.当然,这是一个小问题,但很好。

There's an interesting discussion of this question on this haskell-cafe thread .这个 haskell-cafe thread上有一个关于这个问题的有趣讨论。 Apparently there's a minority viewpoint that holds that the right associativity of $ is "just plain wrong" , and choosing f . g . h $ x显然有少数观点认为$的正确结合性是“完全错误的” ,并选择了f . g . h $ x f . g . h $ x f . g . h $ x over f $ g $ h $ x is one way of side-stepping the issue. f . g . h $ x超过f $ g $ h $ x是回避问题的一种方式。

It's just a matter of style.这只是风格问题。 However, the way the book does it makes more sense to me.然而,这本书的方式对我来说更有意义。 It composes all the functions, and then applies it to the value.它组合了所有函数,然后将其应用于值。

Your method just looks strange, and the last $ is unnecessary.你的方法看起来很奇怪,最后一个$是不必要的。

However, it really doesn't matter.不过,这真的无所谓。 In Haskell, there are usually many, many, correct ways to do the same thing.在 Haskell 中,通常有很多很多正确的方法可以做同样的事情。

I realize this is a very old question, but I think there is another reason for this that hasn't been mentioned.我意识到这是一个非常古老的问题,但我认为还有另一个未提及的原因。

If you are declaring a new point-free function f . g . h如果您要声明一个新的无点函数f . g . h f . g . h f . g . h , the value you pass in will be automatically be applied. f . g . h ,您传入的值将被自动应用。 However, if you write f $ g $ h , it will not work.但是,如果您写f $ g $ h ,它将不起作用。

I think the reason the author prefers the composition method is because it leads to a good practice of building up functions.我认为作者更喜欢组合方法的原因是因为它导致构建函数的良好实践。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM