【发布时间】:2012-02-10 03:19:37
【问题描述】:
可能重复:
Haskell: difference between . (dot) and $ (dollar sign)
我知道“$”将像“f1 (f2 x)”这样的表达式绑定到更简单的形式“f1 $ f2 x”。 “f1.f2 x”与此有何不同?
【问题讨论】:
标签: haskell
可能重复:
Haskell: difference between . (dot) and $ (dollar sign)
我知道“$”将像“f1 (f2 x)”这样的表达式绑定到更简单的形式“f1 $ f2 x”。 “f1.f2 x”与此有何不同?
【问题讨论】:
标签: haskell
嗯,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 相同,标识函数;它只是返回它给出的函数。它之所以有用,是因为它的运算符优先级非常低(实际上是最低的)。
【讨论】:
($) 对于像map ($ 3) [(+5),(*2),(subtract 4)] 这样的事情也很有用(或者至少很酷)
map (`id` 3) [(+5),(*2),(subtract 4)]! :)
($) 和 (.) 都没有做任何特别的事情来“绑定表达式”。他们只是像其他人一样的操作员。您只需要知道它们的定义是什么,以及它们的固定性是什么。第一个:
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,它会起作用。
【讨论】: