函数应用:这里为什么用$?

发布于 2024-07-11 10:21:04 字数 381 浏览 10 评论 0原文

不久前,我问了一个问题关于 $,并得到了有用的答案——事实上,我认为我理解如何使用它。

看来我错了:(

这个例子出现在教程中:

instance Monad [] where
   xs >>= f = concat . map f $ xs

我一生都无法理解为什么在那里使用$;ghci也没有帮助我,因为即使我在那里做的测试似乎也显示出与简单地省略 $ 的版本有人可以帮我澄清这一点吗?

A while ago, I asked a question about $, and got useful answers -- in fact, I thought I understood how to use it.

It seems I was wrong :(

This example shows up in a tutorial:

instance Monad [] where
   xs >>= f = concat . map f $ xs

I can't for the life of me see why $ was used there; ghci isn't helping me either, as even tests I do there seem to show equivalence with the version that would simply omit the $. Can someone clarify this for me?

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

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

发布评论

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

评论(3

佞臣 2024-07-18 10:21:04

这里使用 $ 是因为它的优先级低于普通函数应用程序。
编写此代码的另一种方法如下:

instance Monad [] where
   xs >>= f = (concat . map f) xs

这里的想法是首先构造一个函数 (concat .map f),然后将其应用于其参数 (xs)。 如图所示,这也可以通过简单地在第一部分加上括号来完成。

请注意,在原始定义中省略 $ 是不可能的,这会导致类型错误。 这是因为函数组合运算符(.)的优先级低于正常函数应用程序,有效地将表达式转换为:

instance Monad [] where
  xs >>= f = concat . (map f xs)

这没有意义,因为函数组合运算符的第二个参数是'根本不是一个函数。 尽管下面的定义确实有意义:

instance Monad [] where
  xs >>= f = concat (map f xs)

顺便说一句,这也是我更喜欢的定义,因为在我看来它更清晰。

The $ is used here because it has lower precedence than normal function application.
Another way to write this code is like so:

instance Monad [] where
   xs >>= f = (concat . map f) xs

The idea here is to first construct a function (concat . map f) and then apply it to its argument (xs). As shown, this can also be done by simply putting parenthesis around the first part.

Note that omitting the $ in the original definition is not possible, it will result in a type error. This is because the function composition operator (the .) has a lower precedence than normal function application effectively turning the expression into:

instance Monad [] where
  xs >>= f = concat . (map f xs)

Which doesn't make sense, because the second argument to the function composition operator isn't a function at all. Although the following definition does make sense:

instance Monad [] where
  xs >>= f = concat (map f xs)

Incidentally, this is also the definition I would prefer, because it seems to me to be a lot clearer.

遮云壑 2024-07-18 10:21:04

我想解释为什么恕我直言,这不是那里使用的样式:

instance Monad [] where
  xs >>= f = concat (map f xs)

concat 。 map f 是所谓的 pointfree-style 编写的一个例子; 其中 pointfree 的意思是“没有应用点”。 请记住,在数学中,在表达式 y=f(x) 中,我们说 f 应用于点 x。 在大多数情况下,您实际上可以执行最后一步,将: 替换

f x = something $ x

f = something

f = concat 。 map f,这实际上是pointfree风格。
哪个更清晰是有争议的,但是 pointfree 风格给出了一个不同的观点,这也很有用,所以有时即使不是完全需要的时候也会使用。

编辑:在 Alasdair 发表评论后,我用 pointfree 替换了 pointless,并修复了一些示例,我应该感谢他。

I'd like to explain why IMHO this is not the used style there:

instance Monad [] where
  xs >>= f = concat (map f xs)

concat . map f is an example of so-called pointfree-style writing; where pointfree means "without the point of application". Remember that in maths, in the expression y=f(x), we say that f is applied on the point x. In most cases, you can actually do a final step, replacing:

f x = something $ x

with

f = something

like f = concat . map f, and this is actually pointfree style.
Which is clearer is arguable, but the pointfree style gives a different point of view which is also useful, so sometimes is used even when not exactly needed.

EDIT: I have replaced pointless with pointfree and fixed some examples, after the comment by Alasdair, whom I should thank.

呆头 2024-07-18 10:21:04

这里使用 $ 的原因是 (.) 的类型签名:

(.) :: (b -> c) -> (a -> c) -> a -> c

这里我们有

map f :: [a] -> [[b]]

and

concat :: [[b]] -> [b]

所以我们最终得到

concat . map f :: [a] -> [b]

(.) 的类型可以写成

(.) :: ([[b]] -> ; [b])-> ([a] -> [[b]]) -> [一]-> [b]

如果我们使用 concat 。 map f xs,我们会看到

map f xs :: [[b]]

And so 不能与 (.) 一起使用。 (类型必须是 (.) :: (a -> b) -> a -> b

The reason $ is used here is doe to the type signature of (.):

(.) :: (b -> c) -> (a -> c) -> a -> c

Here we have

map f :: [a] -> [[b]]

and

concat :: [[b]] -> [b]

So we end up with

concat . map f :: [a] -> [b]

and the type of (.) could be written as

(.) :: ([[b]] -> [b]) -> ([a] -> [[b]]) -> [a] -> [b]

If we were to use concat . map f xs, we'd see that

map f xs :: [[b]]

And so cannot be used with (.). (the type would have to be (.) :: (a -> b) -> a -> b

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