2017-09-27 78 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'作爲'$'停止。但是,這需要所有的休息。我忘記了這個概念。 –