2017-09-27 45 views
1

这里是我的代码:

data = [1,2,3,4,5,6,7,8,9,10] 
    cak' [] = [] 
    cak' (x:xs) = 
     if x >= 2 then 
      cak' (x - 2) : cak' (xs) 
     else 
      x : cak' (xs) 
    run = cak' data 

,直到我改变cak' (x - 2) : cak' (xs)cak' $ x - 2 : cak' (xs)它不会工作。它为什么会产生这样的影响?

+3

如果你有任何typecheck错误,请包括他们。了解如何阅读这些内容在Haskell中非常重要(并且帮助很大程度上追踪错误)。 – Thilo

+4

确实。另外,为所有函数添加类型签名是一个非常好的主意,这使得更容易理解你正在做的事情,并且通常还会导致类型错误变得不那么神秘。 – leftaroundabout

回答

6

这是运营商precendence的问题:

  • cak' (x - 2) : cak' (xs)是一样的(cak' (x - 2)) : (cak' (xs))

  • cak' $ (x - 2) : cak' (xs)相同cak' ((x - 2) : cak' (xs))

您可以阅读$为“使用$后的所有内容作为单个参数为$之前的功能“。它有点像一组括号,你不必关闭。

(如 f x,请不要写为 f (x) BTW)
+0

是的,你是对的。我认为'$'停在':'处。我忘了它后面的一切。这对我来说是一个很好的教训。 –

5

功能应用总是结合更加紧密地比任何管道符(如:,尤其是$)。所以cak' (x - 2) : cak' xs事实上被解析为(cak' (x - 2)) : cak' xs,它不会检查(因为x - 2不是一个列表)。

在另一方面,$结合比所有其他标准中缀运算符,因为

Prelude> :i $ 
($) :: (a -> b) -> a -> b -- Defined in ‘GHC.Base’ 
infixr 0 $ 
Prelude> :i : 
... 
infixr 5 : 

...即。 :具有固定性5,但$仅固定性0.因此,cak' $ (x - 2) : cak' xs被解析为(可能是)正确的东西,即cak' ((x - 2) : cak' xs)

+1

现在我明白了。在此之前,我在':'之前查看'cak'$ x - 2:cak'xs'作为'$'停止。但是,这需要所有的休息。我忘记了这个概念。 –