实际上$功能在haskell中做了什么?

Zna*_*atz 9 syntax haskell operators dollar-sign haskell-prelude

我知道

$ :: (a->b) -> a -> b
f $ x = f x
Run Code Online (Sandbox Code Playgroud)

直觉上,在我看来,比如说,1. $将函数的评估延迟到左边2.评估其右边的结果3.将其左边的结果输入到右边.

这对我来说非常有意义,

ghci> length $ [1..5]
5
ghci> ($) length [1..5]
5
Run Code Online (Sandbox Code Playgroud)

我不明白的是为什么,

ghci> ($ [1..5]) length
5
Run Code Online (Sandbox Code Playgroud)

从$的类型来看,是不是它的(第一个)论证应该是一个函数?

And*_*uer 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
Run Code Online (Sandbox Code Playgroud)

也就是说,(+ 4)是功能\x -> x + 4而且(4 +)是功能\y -> 4 + y.在添加的情况下,这些是相同的功能,但现在这并不重要.

现在让我们尝试相同的技巧$:

Prelude> :t ($ [1,2,3,4])
($ [1,2,3,4]) :: Num t => ([t] -> b) -> b
Run Code Online (Sandbox Code Playgroud)

到目前为止,我们得到了惊喜\f -> f $ [1,2,3,4].我们也可以写

Prelude> :t (length $)
(length $) :: [a] -> Int
Run Code Online (Sandbox Code Playgroud)

获得这个功能\l -> length $ l.但是这个怎么样:

Prelude> :t ($ length)
($ length) :: (([a] -> Int) -> b) -> b
Run Code Online (Sandbox Code Playgroud)

这很奇怪,但这很有道理!我们得到了\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] $)
Run Code Online (Sandbox Code Playgroud)

一切都是应有的,因为[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] ($))
Run Code Online (Sandbox Code Playgroud)

所以,回答你的问题:$ [1,2,3,4]被解析为\f -> f $ [1,2,3,4]如此,将它应用到它是完全合理的length.但是($) [1, 2, 3, 4]没有多大意义,因为($)它不被视为中缀运算符.

顺便说一下,$"不做任何事情",可以这么说.它主要用于更可读的输入,因为它具有低优先级,因此我们可以编写f $ g $ h $ x而不是f (g (h x)).


Sco*_*son 10

您的问题实际上是关于所谓的运算符部分.对于Haskell中的任何运算符(我将使用它+作为示例),您可以编写类似(+ arg)或的内容(arg +).这些只是匿名函数的简写语法(\x -> x + arg)(\x -> arg + x).

因此,($ [1..5])语法只意味着(\x -> x $ [1..5])它与(\x -> x [1..5])(即传递[1..5]给作为其参数传递的函数的函数)相同.


drq*_*ver 6

($ [1..5])是一节.这是一个部分应用的运算符.这是一个简写(\f -> f $ [1..5]).

Sections允许您为二元运算符提供一个参数并生成一个函数 - 一个等待剩余参数的函数.

请查看http://www.haskell.org/haskellwiki/Section_of_an_infix_operator