Haskell 我应该在什么时候使用$(是否总是可以用括号替换)?

Haskell 我应该在什么时候使用$(是否总是可以用括号替换)?,haskell,syntax,operators,Haskell,Syntax,Operators,从我所读的内容来看,$被描述为“将函数应用于其参数”。然而,它似乎不像Lisp中的(apply…),因为它是一个二进制运算符,所以它看起来唯一的作用是有时帮助避免使用括号,比如foo$bar-qux,而不是foo(bar-quux)。我理解对了吗?后一种形式被认为是“糟糕的风格”吗?你基本上理解对了——也就是说,大约99%的$Is的使用有助于避免使用括号,是的,在大多数情况下,它似乎比括号更受欢迎 但请注意: > :t ($) ($) :: (a -> b) -> a -> b >:t(元

从我所读的内容来看,
$
被描述为“将函数应用于其参数”。然而,它似乎不像Lisp中的
(apply…
),因为它是一个二进制运算符,所以它看起来唯一的作用是有时帮助避免使用括号,比如
foo$bar-qux
,而不是
foo(bar-quux)
。我理解对了吗?后一种形式被认为是“糟糕的风格”吗?

你基本上理解对了——也就是说,大约99%的$Is的使用有助于避免使用括号,是的,在大多数情况下,它似乎比括号更受欢迎

但请注意:

> :t ($) ($) :: (a -> b) -> a -> b >:t(元) ($):(a->b)->a->b
也就是说,$是一个函数;因此,它可以传递给函数、由它组成的函数以及任何你想用它来做的事情。我想我以前见过人们用组合词来使用它。

$
如果开头和结尾之间的距离大于良好的可读性,则首选括号y认股权证,或者如果有多层嵌套括号

比如说

i (h (g (f x)))
可以重写

i $ h $ g $ f x
换句话说,它表示右关联函数应用程序。这很有用,因为普通函数应用程序与左关联,即

i h g f x
…可以重写如下

(((i h) g) f) x
($)
函数的其他便捷用法包括使用它压缩列表:

zipWith ($) fs xs
这将函数列表中的每个函数应用于列表中相应的参数,并在列表中收集结果。与序列fs x相比,序列fs x将函数列表应用于单个参数
x
,并收集结果;
fs xs
应用于将列表
fs
中的每个函数添加到列表的每个元素
xs

($)的文档回答了您的问题。不幸的是,列表中没有列出它

但是,它列在您可以在此处找到的源代码中:

但是,此模块不直接定义($)。由前者导入的以下内容有:

我将相关代码包括在下面:

infixr 0  $

...

-- | Application operator.  This operator is redundant, since ordinary
-- application @(f x)@ means the same as @(f '$' x)@. However, '$' has
-- low, right-associative binding precedence, so it sometimes allows
-- parentheses to be omitted; for example:
--
-- >     f $ g $ h x  =  f (g (h x))
--
-- It is also useful in higher-order situations, such as @'map' ('$' 0) xs@,
-- or @'Data.List.zipWith' ('$') fs xs@.
{-# INLINE ($) #-}
($)                     :: (a -> b) -> a -> b
f $ x                   =  f x

上面有很多好答案,但有一个遗漏:

$
不能总是用括号代替


但是任何
$
的应用都可以通过使用括号来消除,任何
($)
的使用都可以用
id
来代替,因为
$
是身份函数的一种特殊化
(f$)
的使用可以用
f
来代替,但是类似
($x)
的使用(将函数作为参数,并将其应用于
x
)我看到没有任何明显的替代品。

如果我看一下你的问题和这里的答案,Apocalisp和你都是对的:

  • 在某些情况下,
    $
    优于括号(见他的答案)
  • foo(bar-qux)
    绝对是不错的风格

另外,请查看另一个与您的问题非常相关的SO问题。

关于$signs的菊花链的一个有用的观点是,它可以像Unix管道一样读取,只从右向左。它可以像那样读取“一点”,这就是为什么最好不要这样想。($x)很容易被(\f->f x)代替