Haskell中的$ mean/do是什么?

Edd*_*die 49 syntax haskell operators dollar-sign

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

J. *_*son 65

$是中缀"应用程序".它被定义为

($) :: (a -> b) -> (a -> b)
f $ x = f x

-- or 
($) f x = f x
-- or
($) = id
Run Code Online (Sandbox Code Playgroud)

它有助于避免额外的括号:f (g x) == f $ g x.

对于它来说,一个特别有用的位置是"尾随λ体"

forM_ [1..10] $ \i -> do
  l <- readLine
  replicateM_ i $ print l
Run Code Online (Sandbox Code Playgroud)

相比

forM_ [1..10] (\i -> do
  l <- readLine
  replicateM_ i (print l)
)
Run Code Online (Sandbox Code Playgroud)

或者,巧妙的是,它有时会在表达"将此参数应用于任何函数"时显示为剖面图

applyArg :: a -> (a -> b) -> b
applyArg x = ($ x)

>>> map ($ 10) [(+1), (+2), (+3)]
[11, 12, 13]
Run Code Online (Sandbox Code Playgroud)

  • 我正确地说f(g(hx))== f $ g $ hx? (6认同)
  • 是的.它也写成了`f.G .h $ x`有时,也可能是`(f.g.h)x`. (4认同)
  • 技术说明:AFAIK,"$"的定义目前有点谎言.GHC实际上将它视为语法,以便`runST $ do`惯用法起作用(除了像它真正是函数的部分之类的东西).它应该只是一个函数,但更高级别的类型是一个问题. (4认同)
  • 可能值得指出,与运营商的签名一样,它的PRECEDENCE为0.因此,一切都比$绑定得更紧密. (2认同)

ste*_*hen 14

我想把$符号作为括号的替代.

例如,以下表达式:

take 1 $ filter even [1..10] 
-- = [2]
Run Code Online (Sandbox Code Playgroud)

如果我们不把$?然后我们会得到

take 1 filter even [1..10]
Run Code Online (Sandbox Code Playgroud)

和编译器现在会抱怨,因为它可能会认为我们正在试图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]