2014-10-06 52 views
0

以下函數的要點是獲取列表並將列表拆分爲2個列表的元組。第一個列表將維護偶數索引項目,第二個列表將維護奇數索引項目。 「Pos」是目前的位置。 (在函數調用中傳入0)。列表中通過了最初的元組([],[])Haskell - 函數中的非窮舉模式

split :: [Integer] -> ([Integer],[Integer]) -> Integer -> ([Integer], [Integer]) 
split [] (x,y) _ = (x,y) 
split (x:xs) ((y:ys),(z:zs)) pos 
    | pos `mod` 2 == 0 = doSplit xs ((y:ys) ++ [x], (z:zs)) (pos + 1) 
    | otherwise   = doSplit xs ((y:ys), (z:zs) ++ [x]) (pos + 1) 

Haskell是報告

*** Exception: split.hs:(113,1)-(116,73): Non-exhaustive patterns in function split 

我明白,它認爲我還沒有涵蓋「某些情況下」應覆蓋但是我覺得我已經涵蓋了所有的情況。

如果列表爲空 - >返回在 中傳遞的列表的元組否則 - >將x粘貼到其中一個列表上並在xs上遞歸。

從我的角度來看,這個函數是嚴格遞減的,直到xs變成[],在這種情況下它會停止。

我錯過了什麼嗎?

+3

如果列表不爲空,會發生什麼,但你的元組包含一個空列表? – Zeta 2014-10-06 20:33:55

+0

你可以使用'even pos'而不是'pos \'mod \'2 == 0'。 (我意識到這並不能解決你的問題,但Zeta確實如此) – 2014-10-06 20:37:15

+0

它應該沒關係,函數不會在元組上遞歸。 是[] ++ [x]不是一個有效的語句嗎?事實上,這應該幾乎總是如此,因爲傳入的元組實際上是空的。有沒有辦法讓我指定我希望它在兩種情況下都能進行遞歸? – Aserian 2014-10-06 20:38:20

回答

4

當第一個列表非空,但tuple參數中的一個(或兩個)列表爲空時,則不匹配。

split [1] ([], []) 

但是你的第二句話似乎並不需要在元組或者列表是非空的,所以你可以將其更改爲:

split (x:xs) (ys,zs) pos 
    | pos `mod` 2 == 0 = doSplit xs (ys ++ [x], zs) (pos + 1) 
    | otherwise   = doSplit xs (ys, zs ++ [x]) (pos + 1) 
+0

謝謝!我想我沒有意識到,(y:ys)推斷了一個cons pair,而不僅僅是「what's there」。 – Aserian 2014-10-06 20:46:44

+1

@Aserian該':'實際上是一個列表的兩個構造函數之一,另一個是'[]'。你可以並且應該像對待任何其他構造函數一樣對待它,以進行模式匹配。 – bheklilr 2014-10-06 21:00:06

+1

@Aserian與任何列表匹配的模式都是'ys'。 *類型*表示它是一個列表;你不需要在變量中使用任何特殊符號來表明它是一個列表。 'y:ys'只能是「對某事的東西」;無論您爲「y」和「ys」選擇什麼值,該表達式都無法等於'[]'。 – Ben 2014-10-07 03:17:44

相關問題