9

从我正在阅读的内容来看,$它被描述为“将函数应用于其参数”。然而,它似乎不像(apply ...)在 Lisp 中那样工作,因为它是一个二元运算符,所以它看起来唯一的作用是有时有助于避免括号,比如foo $ bar quux代替foo (bar quux). 我理解对了吗?后一种形式是否被认为是“坏风格”?

4

5 回答 5

19

$当开始和结束括号之间的距离大于良好的可读性保证时,或者如果您有多层嵌套括号,则首选括号。

例如

i (h (g (f x)))

可以改写

i $ h $ g $ f x

换句话说,它代表了右关联函数的应用。这很有用,因为普通函数应用程序关联到左侧,即以下

i h g f x

...可以改写如下

(((i h) g) f) x

该函数的其他方便用途($)包括使用它压缩列表:

zipWith ($) fs xs

这会将函数列表中的每个函数应用于列表中fs的相应参数xs,并将结果收集到列表中。与之相比,sequence fs x它将函数列表应用于fs单个参数x并收集结果;并将fs <*> xs列表中的每个函数应用于列表fs的每个元素xs

于 2008-12-28T10:39:52.833 回答
6

您的理解基本正确——也就是说,大约 99% 的 $ 使用是为了帮助避免括号,是的,在大多数情况下,它似乎确实比括号更受欢迎。

但请注意:

> :t ($)
($) :: (a -> b) -> a -> b

也就是说,$是一个函数;因此,它可以被传递给函数,由它组成,以及任何你想用它做的事情。我想我以前见过人们使用组合器来使用它。

于 2008-12-28T09:46:08.713 回答
4

($) 的文档回答了您的问题。不幸的是,它没有列在Prelude 的自动生成的文档中

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

http://darcs.haskell.org/packages/base/Prelude.hs

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

http://darcs.haskell.org/packages/base/GHC/Base.lhs

我在下面包含了相关代码:

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
于 2008-12-28T12:28:56.497 回答
4

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

$ 不能总是用括号代替

但是任何应用 of$都可以通过使用括号来消除,任何使用 of($)都可以替换为id,因为$它是恒等函数的一个特化。的用法(f$)可以替换为f,但是我看到的类似($x)(将函数作为参数并将其应用于x)的用法没有任何明显的替换。

于 2008-12-30T03:01:48.060 回答
1

如果我在这里查看您的问题和答案,Apocalisp 和您都是对的:

  • $在某些情况下优先于括号(见他的回答)
  • foo (bar quux)风格肯定不错!

另外,请检查. (dot) 和 $ (dollar sign),另一个与您非常相关的 SO 问题。

于 2009-06-26T06:10:28.560 回答