【问题标题】:What does $ mean/do in Haskell?$ 在 Haskell 中是什么意思/做什么?
【发布时间】:2013-10-31 12:32:42
【问题描述】:

当您编写稍微复杂一点的函数时,我注意到$ 被大量使用,但我不知道它的作用是什么?

【问题讨论】:

标签: haskell syntax operators dollar-sign


【解决方案1】:

$ 是中缀“应用程序”。它被定义为

($) :: (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
  • 技术说明:AFAIK,目前$的定义有点假。 GHC 实际上将其视为语法,以便 runST $ do 成语起作用(除了在它真正是函数的部分之外)。它应该只是一个函数,但更高级别的类型是一个问题。
  • &lt;$&gt; 只是中缀fmap。据我所知,它并没有什么特别之处。
  • 可能值得指出,连同运算符的签名,它的 PRECEDENCE 为 0。因此,一切都比 $ 绑定得更紧密。
【解决方案2】:

我喜欢将 $ 符号视为括号的替代品。

例如下面的表达式:

take 1 $ filter even [1..10] 
-- = [2]

如果我们不放 $ 会发生什么?然后我们会得到

take 1 filter even [1..10]

编译器现在会抱怨,因为它会认为我们正在尝试将 4 个参数应用于 take 函数,参数为 1 :: Intfilter :: (a -&gt; Bool) -&gt; [a] -&gt; [a]even :: Integral a =&gt; a -&gt; 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]

【讨论】:

  • 编译器如何推断括号末尾的位置?
  • 当它找到下一个$ 符号时,否则为行尾。
猜你喜欢
  • 2015-09-14
  • 2016-09-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-12-27
  • 2017-09-12
  • 1970-01-01
相关资源
最近更新 更多