当你编写稍微复杂一些的函数时,我注意到经常使用
$
,但我不知道它是干什么用的?$
,但我不知道它是干什么用的?$
是中缀运算符“应用”。它的定义是
($) :: (a -> b) -> a -> b
f $ x = f x
-- or
($) f x = f x
-- or
($) = id
这对于避免额外的括号非常有用:f (g x) == f $ g x
。
它特别适用于“尾随 lambda 体”这样的情况。
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]
f . g . h $ x
,这也可以表示为 (f . g . h) x
。 - J. Abrahamson$
的定义有点不准确。在 GHC 中,它实际上被视为语法,这样 runST $ do
这种习惯用法才能工作(除了像 sections 这样真正是函数的地方)。本应该只是一个函数,但高阶类型是个问题。 - Philip JF:t
是 ($) :: (a -> b) -> a -> b
。 - johnbakers我喜欢把美元符号看作是括号的替代。
例如,下面的表达式:
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]
$
符号或者行尾时。 - Dhia