2011-10-22 66 views
1

我對Haskell很新,只是開始學習它。 我正在使用「學習你一個偉大的好事Haskell!」教程開始,看到解決的例子「3N + 1」的問題:過濾列表清單

chain :: (Integral a) => a -> [a] 
chain 1 = [1] 
chain n 
    | even n = n:chain (n `div` 2) 
    | odd n = n:chain (n*3 + 1) 

numLongChains :: Int 
numLongChains = length (filter isLong (map chain [1..100])) 
    where isLong xs = length xs > 15 

所以,numLongChains統計更長15個步驟,從1所有號碼爲100。

現在,我想所有連鎖我自己的:

numLongChains' :: [Int] 
numLongChains' = filter isLong (map chain [1..100]) 
    where isLong xs = length xs > 15  

所以現在,我不想計算這些鏈,但返回與這些鏈條過濾列表。 但現在我在編譯時出現錯誤:

Couldn't match expected type `Int' with actual type `[a0]' 
Expected type: Int -> Bool 
    Actual type: [a0] -> Bool 
In the first argument of `filter', namely `isLong' 
In the expression: filter isLong (map chain [1 .. 100]) 

可以採取什麼問題嗎?

回答

3

numLongChains的型號簽名可能不正確。根據你想要做什麼,下面的一個需要:

  • 你只是想算的鎖鏈,你的函數numLongChains顯然應返回一個數字,改變第一行length $ filter isLong (map chain [1..100])和類型Int
  • 您想要返回長鏈長度的列表。在這種情況下,類型簽名很好,但你需要返回一個長度。我建議你,在過濾和篩選之前計算長度。該功能的主體變成了filter (>15) (map (length . chain) [1..100])
  • 您想返回所有長度超過15個字符的鏈。只需將簽名更改爲[[Int]](鏈表(列表)Int s),您就可以了。
+0

謝謝!真的是我的錯,用[[Int]]解決了問題 – dmitry

+0

@dmitry請接受這個答案來幫助別人。只需點擊答案評分下方的綠色勾號即可。 – fuz

1

FUZxxl是正確的。您將要將您的功能的類型簽名更改爲[[Int]]。由於您正在篩選列表並只選擇足夠長的列表,因此您將返回列表列表。

關於閱讀Haskell編譯時調試器/錯誤的一個注意事項。這個錯誤看起來很奇怪。它說你有[a0] -> Bool但你期待Int -> Bool。這是因爲類型檢查器假定,從您的numLongChains函數的簽名中,您將需要一個篩選函數來檢查Ints並返回可接受的列表。對列表進行過濾並獲取[Int]的唯一方法是獲取一個需要Int s並返回Bool s (Int -> Bool)的函數。相反,它會看到一個檢查長度的函數。長度需要一個列表,所以它猜測你寫了一個函數來檢查列表。 ([a0] -> Bool)。有時候,檢查者並不像你期望的那麼友善,但是如果你看起來足夠努力,你會看到10次中有9次,難以辨認的錯誤是諸如假設的結果。

+0

Erik,也謝謝你,但我所知道的是,現在對我來說太難了:)而且關於我從命令式語言中知道的隱式轉換的邪惡 – dmitry