当您编写稍微更复杂的函数时,我注意到它$
被大量使用但我不知道它的作用是什么?
问问题
43281 次
2 回答
75
$
是中缀“应用程序”。它被定义为
($) :: (a -> b) -> (a -> b)
f $ x = f x
-- or
($) f x = f x
-- or
($) = id
这对于避免额外的括号很有用:f (g x) == f $ g x
.
一个特别有用的位置是“尾随 lambda body”,例如
forM_ [1..10] $ \i -> do
l <- readLine
replicateM_ i $ print l
相比
forM_ [1..10] (\i -> do
l <- readLine
replicateM_ i (print l)
)
或者,巧妙的是,它有时会在表达“将此参数应用于任何函数”时显示为分段
applyArg :: a -> (a -> b) -> b
applyArg x = ($ x)
>>> map ($ 10) [(+1), (+2), (+3)]
[11, 12, 13]
于 2013-10-22T14:56:39.280 回答
24
我喜欢将 $ 符号视为括号的替代品。
例如,下面的表达式:
take 1 $ filter even [1..10]
-- = [2]
如果我们不放 $ 会发生什么?然后我们会得到
take 1 filter even [1..10]
并且编译器现在会抱怨,因为它会认为我们正在尝试将 4 个参数应用于take
函数,参数为1 :: Int
, filter :: (a -> Bool) -> [a] -> [a]
, even :: Integral a => a -> Bool
, [1..10] :: [Int]
。
这显然是不正确的。那么我们能做些什么呢?好吧,我们可以在表达式周围加上括号:
(take 1) (filter even [1..10])
现在这将减少为:
(take 1) ([2,4,6,8,10])
然后变成:
take 1 [2,4,6,8,10]
但我们并不总是想写括号,尤其是当函数开始相互嵌套时。另一种方法是将$
符号放在括号对的位置之间,在这种情况下将是:
take 1 $ filter even [1..10]
于 2016-05-14T15:25:41.483 回答