点(.)和美元符号($)的区别是什么?
根据我的理解,它们都是不需要使用括号的语法糖。
点(.)和美元符号($)的区别是什么?
根据我的理解,它们都是不需要使用括号的语法糖。
当前回答
($)允许函数链接在一起,而不需要添加括号来控制求值顺序:
Prelude> head (tail "asdf")
's'
Prelude> head $ tail "asdf"
's'
复合操作符(.)创建一个新函数,但不指定参数:
Prelude> let second x = head $ tail x
Prelude> second "asdf"
's'
Prelude> let second = head . tail
Prelude> second "asdf"
's'
上面的例子可以说是说明性的,但并没有真正显示使用组合的便利性。这里还有一个类比:
Prelude> let third x = head $ tail $ tail x
Prelude> map third ["asdf", "qwer", "1234"]
"de3"
如果我们只使用一次third,我们可以通过使用lambda来避免命名:
Prelude> map (\x -> head $ tail $ tail x) ["asdf", "qwer", "1234"]
"de3"
最后,复合让我们避免lambda:
Prelude> map (head . tail . tail) ["asdf", "qwer", "1234"]
"de3"
其他回答
我想举个简短的例子。而不是$将有助于澄清事情。
double x = x * 2
triple x = x * 3
times6 = double . triple
:i times6
times6 :: Num c => c -> c
请注意,times6是一个由函数组合创建的函数。
简短而甜蜜的版本:
($)调用作为其左实参的函数对作为其右实参的值进行调用。 (.)将作为其左参数的函数组合到作为其右参数的函数上。
关于$最重要的部分是它具有最低的操作符优先级。
如果你输入info,你会看到:
λ> :info ($)
($) :: (a -> b) -> a -> b
-- Defined in ‘GHC.Base’
infixr 0 $
这告诉我们它是一个具有右结合性的中缀运算符,具有最低的可能优先级。普通函数应用程序是左关联的,具有最高优先级(10)。$正好相反。
所以我们在普通函数application或using()不起作用的地方使用它。
例如,这是可行的:
λ> head . sort $ "example"
λ> e
但这不是:
λ> head . sort "example"
因为。(sort "example")的优先级比sort低,类型是[Char]
λ> :type (sort "example")
(sort "example") :: [Char]
但是。需要两个函数,没有一个简单的方法来实现因为排序和操作的顺序。
还要注意,($)是专门用于函数类型的标识函数。恒等函数是这样的:
id :: a -> a
id x = x
While($)是这样的:
($) :: (a -> b) -> (a -> b)
($) = id
注意,我有意在类型签名中添加了额外的括号。
($)的使用通常可以通过添加圆括号来消除(除非在节中使用运算符)。例如:f $ g x变成f (g x)。
(.)的使用通常稍难替换;它们通常需要一个lambda或显式函数形参的引入。例如:
f = g . h
就变成了
f x = (g . h) x
就变成了
f x = g (h x)
我的规则很简单(我也是初学者):
不要使用。如果要传递参数(调用函数),和 如果没有参数,不要使用$(合成一个函数)
这是
show $ head [1, 2]
但从来没有:
show . head [1, 2]