为什么这个美元符号构造不起作用?

Rub*_*ben 3 haskell dollar-sign

是的,另一个美元符号问题.对不起......(我使用了搜索功能!)

我的课程功能编程教授告诉我们,美元符号'有点添加一个开头括号,然后在结尾添加一个'(这里大致粗略地描述的方式大致相同).所以

fibs = 0 : 1 : zipWith (+) fibs $ tail fibs
Run Code Online (Sandbox Code Playgroud)

应该相当于

fibs = 0 : 1 : zipWith (+) fibs (tail fibs)
Run Code Online (Sandbox Code Playgroud)

嗯,事实并非如此.第二件事编译得很好,第一件事就是错误:

jkjj.hs:1:8:
    Couldn't match expected type `[a1] -> [a1]' with actual type `[a0]'
    The first argument of ($) takes one argument,
    but its type `[a0]' has none
    In the expression: 0 : 1 : zipWith (+) fibs $ tail fibs
    In an equation for `fibs':
        fibs = 0 : 1 : zipWith (+) fibs $ tail fibs

fibonacci.hs:1:16:
    Couldn't match expected type `[a0]' with actual type `[a1] -> [a1]'
    In the return type of a call of `zipWith'
    Probable cause: `zipWith' is applied to too few arguments
    In the second argument of `(:)', namely `zipWith (+) fibs'
    In the second argument of `(:)', namely `1 : zipWith (+) fibs'
Run Code Online (Sandbox Code Playgroud)

当然,因为$是一个函数,例如:

fibs = 0 : 1 $ zipWith (+) fibs (tail fibs)
Run Code Online (Sandbox Code Playgroud)

不会起作用,所以至少我教授给出的解释是过于简单化了.在写这篇文章时,我试图放置括号,以便错误相同.我有:

fibs = (0 : 1 : zipWith (+) fibs) $ tail fibs
Run Code Online (Sandbox Code Playgroud)

fibs =(0:1:zipWith(+)fibs)(尾纤)

这两个都给了我完全相同的错误信息(当然除了列号).为什么是这样?ab $ cd相当于(ab)(cd)而不是ab(cd)?我认为这都与函数优先级和/或关联性有关,但我不知道具体细节.我不知道你怎么能看到一个函数有什么优先级(除了尝试很多组合),我也无法用google找到它.

我希望有人可以帮我解决这个问题!

Chr*_*lor 9

这是一个优先问题.你有两个缀运营商这里,:$.作为中缀运算符,:优先级高于$,因此它更紧密地绑定.你可以在ghci中询问优先级

>> :i :
data [] a = ... | a : [a]        -- Defined in `GHC.Types`
infixr 5 :

>> :i $
($) :: (a -> b) -> a -> b
infixr 0 $
Run Code Online (Sandbox Code Playgroud)

infixr意味着操作符向右分组(以便表达式a + b + c被解释为a + (b + c)),并且数字给出优先级(更高=更紧密的绑定).

此外,您需要知道函数应用程序具有最高优先级(最严格的绑定).所以在你的两个表达式中,这一个

fibs = 0 : 1 : zipWith (+) fibs (tail fibs)
Run Code Online (Sandbox Code Playgroud)

被分组为

fibs = 0 : (1 : (zipWith (+) fibs (tail fibs)))
Run Code Online (Sandbox Code Playgroud)

而这个

fibs = 0 : 1 : zipWith (+) fibs $ tail fibs
Run Code Online (Sandbox Code Playgroud)

被分组为

fibs = (0 : (1 : (zipWith (+) fibs))) $ (tail fibs)
Run Code Online (Sandbox Code Playgroud)

这会给你一个错误,因为左边的表达式$应该是一个函数,但在你的情况下它是一个列表.


ick*_*fay 7

是的,a b $ c d相当于(a b) (c d).这是因为美元符号不是一个语法结构:它是一个像其他运算符一样的中缀运算符,并且必须遵守相同的规则.它只是$应用一个函数,并且具有非常低的优先级,从而赋予其行为.

您询问了如何查找运算符的优先级.你可以:info在GHCi中使用:

ghci> :info $
($) :: (a -> b) -> a -> b   -- Defined in `GHC.Base'
infixr 0 $
Run Code Online (Sandbox Code Playgroud)

注意最后一行.这表示它是优先级为0的右关联运算符.
(优先级从0到9)

询问GHCi有:以下几点:

ghci> :info :
data [] a = ... | a : [a]   -- Defined in `GHC.Types'
infixr 5 :
Run Code Online (Sandbox Code Playgroud)

所以:也是一个右关联运算符,但它具有优先级5.由于:具有更高的优先级$,因此它将被分组为$左操作数.

  • 还要注意```运算符的优先级为'5`,这似乎是他们所具有的特定问题. (2认同)