2013-03-09 86 views
2

我正在學習一些Haskell,我試圖讓我的頭瞭解模式匹配是如何工作的。 這樣做,我寫了一個簡單的nth函數。Haskell模式匹配出錯了

nth' :: Integer -> [a] -> a 
nth' n [] = error "Index out of bound" 
nth' n (x:xs) = if n == 0 then x else nth' (n - 1) xs 

這第一次實施似乎按預期工作。

-- nth' 25 ['a'..'z'] 
-- 'z' 
-- nth' 26 ['a'..'z'] 
-- *** Exception: Index out of bound 

然而,當我重構它與模式匹配替換if語句,我最終得到了「索引出界的」例外,我很清楚不應該。

nth' :: Integer -> [a] -> a 
nth' _ [] = error "Index out of bound" 
nth' 0 (x:[]) = x 
nth' n (_:xs) = nth' (n - 1) xs 

-- nth' 2 ['a'..'z'] 
-- *** Exception: Index out of bound 

我在做什麼錯?

回答

6

有問題的條款:

nth' 0 (x:[]) = x 

它只有一個元素的列表匹配。嘗試去改變它:

nth' 0 (x:_) = x 
+0

權......這就是爲什麼'第n個」 25 'A' .. 'Z']'不實際返回 'Z'! 非常感謝! – 2013-03-09 16:28:39

13

模式x:[]與僅包含一個元素的列表匹配。所以你的nth' 0 (x:[])大小寫只有在第一個參數是0而第二個參數是一個元素列表時纔會被執行。如果第二個參數是一個具有多個參數的列表,它將進入最後一種情況。

您需要將第二種情況更改爲nth' 0 (x:_) = x,以便無論列表中有多少元素(只要至少有一個元素),它都會匹配。

1

嘗試:

nth' :: Integer -> [a] -> a 
    nth' _ [] = error "Index out of bound" 
    -- nth' 0 (x:[]) = x -- matches one element list x:[] = [x] 
    nth' 0 (x:_) = x  -- matches first element and everything (not just empty list) 
    nth' n (_:xs) = nth' (n - 1) xs