2017-07-06 107 views
1

我是一名Haskell初學者,在真實世界Haskell的第2章中練習,在這裏你寫一個返回列表的倒數第二個元素的函數。爲什麼這個Haskell函數推斷爲這種類型?

我已經寫了下面的函數來試圖解決這個問題:

-- file: \Learn Haskell\lastButOne.hs 
lastButOne xs = if length xs == 2 
       then head xs 
       else lastButOne tail xs 

我不明白這是錯誤的編譯器會拋出:

lastButOne.hs:2:1: error: 
    • Couldn't match type ‘[a] -> [a]’ with ‘[t]’ 
     Expected type: ([a] -> [a]) -> [t] -> t 
     Actual type: [t] -> t 
    • Relevant bindings include 
     lastButOne :: ([a] -> [a]) -> [t] -> t (bound at lastButOne.hs:2:1) 

據我瞭解,ghci的認爲我的功能應該與它的類型不同,但我不明白爲什麼會發生這種情況,或者我該如何解決它。

編輯:謝謝你的答案!我已經更新了我的代碼:

-- file: \Learn Haskell\lastButOne.hs 
lastButOne xs = if length xs == 2 
       then head xs 
       else if length xs < 2 
        then error "This list does not have a second-to-last element." 
        else lastButOne (tail xs) 

這消除其中tail xs被解釋爲兩個參數,而不是單一的表達錯誤。我還添加了一些確保列表不會太短的代碼。 Willem Van Onsem的解決方案更好,但作爲一項練習,我想我會想出一個解決方案,只使用本書中介紹的概念。

+1

'lastButOne尾xs'是'(lastButOne尾)xs',不'lastButOne(尾XS)' – amalloy

+1

你應該避免'head','儘可能多的尾巴「。他們不是慣用的Haskell,因爲1)如果你在空列表上使用它們,他們可能會崩潰你的程序,2)模式匹配更容易使用,也更方便。 – chi

回答

2

的問題是與線:

 else lastButOne tail xs 

它應該是:

 else lastButOne (tail xs) 

否則ghci東西,你給lastButOne兩個參數:tailxs

但是,您可以使代碼更優雅:

lastButOne [x,_] = x 
lastButOne xs = lastButOne $ tail xs 

而且你必須找到一種方法來解決列表和一個元素,而空單。此時該功能將開始循環。一個想法可能是錯誤的這些列表,如:

lastButOne [x,_] = x 
lastButOne (_:xs) = lastButOne xs 
lastButOne [] = error "The list has no last but one element." 
相關問題