2017-10-08 52 views
2

所以我創造了這個功能,給我的 「N」 第一要素從列表中,「(B:BS);函數take6錯誤中的非窮舉模式?

1 module Sexta where 
2 
3 take6::Int->[a]->[a] 
4 take6 n (b:bs) = if n<=0 then [] 
5     else [b] ++ (take6 (n-1) bs) 

的問題是,當我嘗試:take6 2 [],它表明:

*** Exception: sexta.hs:(4,1)-(6,15): Non-exhaustive patterns in function take6 

我不爲什麼,因爲當我嘗試這手:

take6 2 [] 
    = [] ++take6 1 [] 
    = [] ++[]++take6 0 [] 
    = [] ++[]++[] 
    = [] 

回答

3

在程序中這樣寫:

take6 n (b:bs) = ... 

但在這裏,你這樣使用一個模式(b:bs)這是列表的「利弊」的構造。 cons構造函數的頭部爲b,尾部爲bs。列表類型有兩個構造函數:我們已經在這裏討論過的「cons」和空列表[]。 Haskell抱怨說,它無法爲第二個參數的空列表模式找到一個子句。所以你的功能需要用形狀定義:

take6 n [] = ... 
take6 n (b:bs) = ... 

現在問題仍然是在這裏做什麼。無論什麼樣的,我們採取空單的情況下,我們不能發出任何元素了,所以你可能要返回空列表,因此:

take6 _ [] = [] 

而且你做確實n之間的區別小於或等於零在這種情況下,結果是一個空列表:

take6 n (b:bs) | n <= 0 = [] 

但還存在n > 0的情況。在這種情況下,我們確實需要在take6 (n-1) bs之前加上b。然而,一個更有效的方式來預先考慮,再次使用「缺點」構造記:

或全部:

take6 :: Int -> [a] -> [a] 
take6 _ [] = [] 
take6 n (b:bs) | n <= 0 = [] 
       | otherwise = b : take6 (n-1) bs 
+0

是的,它可能更有效。但是,當GHC在啓用優化的情況下運行時,它們最終應該是相同的。我沒有檢查過這個例子,但是有一些特殊的規則將文字列表排除爲'build'形式,它應該與'(++)'中的'foldr'形式融合。在這種情況下,依靠這種優化是毫無意義的,但我認爲使用'[a]'作爲foldMap的monoid目標時更重要。 – dfeuer

2

模式b:bs不匹配空單需要有單獨的情況下公頃ndle空列表。

2

您在檢查n之前解構了列表,因此即使它爲0,您也要求該列表不爲空。您可以使用警衛來處理這種情況,但在列表太短的情況下,這無助於您。