可能重复:
Haskell: difference between . (dot) and $ (dollar sign)
我理解“$”将类似“f1(f2 x)”的表达式绑定到更简单的形式“f1 $ f2 x”。 “f1.f2 x”与此有何不同?
答案 0 :(得分:7)
嗯,f1 . f2 x
是f1
和f2 x
的组合。您可能意为(f1 . f2) x
或等同于f1 . f2 $ x
;即f1
和f2
的组成,适用于x
。
通过查看类型可以找到答案:
($) :: (a -> b) -> a -> b
(.) :: (b -> c) -> (a -> b) -> a -> c
简单地说,($)
将一个函数应用于其参数, 1 和(.)
composes它的两个参数。两条链
f . g . h $ x
和
f $ g $ h $ x
是等价的;前者通常是首选,因为使用剪切和粘贴更容易将组合物重构为其自身的功能,但这不是普遍的偏好。它的视觉噪音也有点低。
1 的确,($)
与身份函数id
相同;它只返回它给出的函数。它只是有用的,因为给它的运算符优先级非常低(实际上是最低的)。
答案 1 :(得分:6)
($)
和(.)
都没有为“绑定表达式”做任何特别的事情。他们只是像其他人一样的运营商。您需要知道的只是它们的定义,以及它们的固定性。第一个:
infixr 0 $
f $ x = f x
所以它是功能应用程序,具有非常低的优先级和右关联性。因此,如果您有f x $ g y z
,则表示(f x) (g y z)
等同于f x (g y z)
。它主要用于避免使用括号。
第二个:
infixr 9 .
(.) f g x = f (g x)
这看起来很相似,但是(.)
在两个函数上运行,而不是函数和参数,并且具有非常高的优先级。因此,如果您有(f x . g y) z
,则表示(f x) ((g y) z)
等同于f x (g y z)
。
关键区别在于,使用(.)
可以将多个函数链接在一起,例如f1 . f2 . f3
,而使用($)
,您只能将更多函数应用于结果。因此,在像f x $ g y $ h z
这样的表达式中,如果您决定要用整个值列表替换单个值z
,则不能只编写map (f x $ g y $ h) zs
因为函数没有任何内容要应用于带括号的表达式。如果您改为编写类似f x . g y . h $ z
的内容,则只需删除最终的函数应用程序并获取map (f x . g y . h) zs
即可。