我知道
$ :: (a->b) -> a -> b
f $ x = f x
直觉上,在我看来,喜欢说, 1. $将功能评估推迟到左侧 2.评估其权利 3.将其左侧的结果输入右侧。
这对我来说非常有意义,
ghci> length $ [1..5]
5
ghci> ($) length [1..5]
5
我不明白为什么,
ghci> ($ [1..5]) length
5
从$的类型判断,是不是它的(第一个)参数应该是一个函数?
答案 0 :(得分:16)
这与解析有关。在Haskell中,您可以编写(op arg)
,其中op
是一个中缀运算符。这与((op) arg)
不同。你也可以写(arg op)
!例如:
GHCi, version 7.0.3: http://www.haskell.org/ghc/ :? for help
Prelude> :t (+ 4)
(+ 4) :: Num a => a -> a
Prelude> :t (4 +)
(4 +) :: Num a => a -> a
也就是说,(+ 4)
是函数\x -> x + 4
,(4 +)
是函数\y -> 4 + y
。在添加的情况下,这些功能相同,但现在这并不重要。
现在让我们在$
上尝试相同的技巧:
Prelude> :t ($ [1,2,3,4])
($ [1,2,3,4]) :: Num t => ([t] -> b) -> b
到目前为止,我们得到了\f -> f $ [1,2,3,4]
。我们也可以写
Prelude> :t (length $)
(length $) :: [a] -> Int
获取函数\l -> length $ l
。但是这个怎么样:
Prelude> :t ($ length)
($ length) :: (([a] -> Int) -> b) -> b
这很奇怪,但这很有道理!我们得到了\f -> f $ length
,即功能,它希望获得一个f
类型([a] -> Int) -> b)
的函数,该函数将应用于length
。还有第四种可能性:
Prelude> :t ([1,2,3,4] $)
<interactive>:1:2:
Couldn't match expected type `a0 -> b0' with actual type `[t0]'
In the first argument of `($)', namely `[1, 2, 3, 4]'
In the expression: ([1, 2, 3, 4] $)
一切都是应有的,因为[1,2,3,4]
不是一个功能。如果我们在括号中写$
怎么办?然后它作为中缀运算符的特殊含义消失了:
Prelude> :t (($) length)
(($) length) :: [a] -> Int
Prelude> :t (($) [1,2,3,4])
<interactive>:1:6:
Couldn't match expected type `a0 -> b0' with actual type `[t0]'
In the first argument of `($)', namely `[1, 2, 3, 4]'
In the expression: (($) [1, 2, 3, 4])
Prelude> :t (length ($))
<interactive>:1:9:
Couldn't match expected type `[a0]'
with actual type `(a1 -> b0) -> a1 -> b0'
In the first argument of `length', namely `($)'
In the expression: (length ($))
Prelude> :t ([1,2,3,4] ($))
<interactive>:1:2:
The function `[1, 2, 3, 4]' is applied to one argument,
but its type `[t0]' has none
In the expression: ([1, 2, 3, 4] ($))
因此,要回答您的问题:$ [1,2,3,4]
被解析为\f -> f $ [1,2,3,4]
,因此将其应用于length
非常有意义。但是($) [1, 2, 3, 4]
没有多大意义,因为($)
不被视为中缀运算符。
顺便说一下,$
做“什么都不做”,可以这么说。它主要用于更易读的输入,因为它的优先级较低,因此我们可以编写f $ g $ h $ x
而不是f (g (h x))
。
答案 1 :(得分:10)
您的问题实际上是关于所谓的运算符部分。对于Haskell中的任何运算符(我将使用+
作为示例),您可以编写类似(+ arg)
或(arg +)
的内容。这些只是匿名函数(\x -> x + arg)
和(\x -> arg + x)
的简写语法。
因此,($ [1..5])
语法只意味着(\x -> x $ [1..5])
与(\x -> x [1..5])
相同(即将[1..5]
传递给作为其参数传递的函数的函数)。
答案 2 :(得分:6)
($ [1..5])
是一个部分。这是一个部分应用的运算符。这是(\f -> f $ [1..5])
的简写。
Sections允许您为二元运算符提供一个参数并生成一个函数 - 一个等待剩余参数的函数。
查看http://www.haskell.org/haskellwiki/Section_of_an_infix_operator