从我正在阅读的内容来看,$
它被描述为“将函数应用于其参数”。然而,它似乎不像(apply ...)
在 Lisp 中那样工作,因为它是一个二元运算符,所以它看起来唯一的作用是有时有助于避免括号,比如foo $ bar quux
代替foo (bar quux)
. 我理解对了吗?后一种形式是否被认为是“坏风格”?
5 回答
$
当开始和结束括号之间的距离大于良好的可读性保证时,或者如果您有多层嵌套括号,则首选括号。
例如
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
。
您的理解基本正确——也就是说,大约 99% 的 $ 使用是为了帮助避免括号,是的,在大多数情况下,它似乎确实比括号更受欢迎。
但请注意:
> :t ($) ($) :: (a -> b) -> a -> b
也就是说,$是一个函数;因此,它可以被传递给函数,由它组成,以及任何你想用它做的事情。我想我以前见过人们使用组合器来使用它。
($) 的文档回答了您的问题。不幸的是,它没有列在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
上面有很多好的答案,但有一个遗漏:
$
不能总是用括号代替
但是任何应用 of$
都可以通过使用括号来消除,任何使用 of($)
都可以替换为id
,因为$
它是恒等函数的一个特化。的用法(f$)
可以替换为f
,但是我看到的类似($x)
(将函数作为参数并将其应用于x
)的用法没有任何明显的替换。
如果我在这里查看您的问题和答案,Apocalisp 和您都是对的:
$
在某些情况下优先于括号(见他的回答)foo (bar quux)
风格肯定不错!
另外,请检查. (dot) 和 $ (dollar sign),另一个与您非常相关的 SO 问题。