[英]Haskell Beginner, recursive function, list, Error: Non-exhaustive patterns
我嘗試編寫一個函數[int]-> int以計算具有迭代函數的整數列表的總和(結果應等於內置函數sum)
19>sumList :: [Int] -> Int
20>sumList [list] | length[list] > 0 = [list]!!0 + sumList (drop 1 [list])
21> | otherwise = 0
如果我嘗試運行它,這就是結果
uebung1.lhs:20:2: warning: [-Wincomplete-patterns]
Pattern match(es) are non-exhaustive
In an equation for ‘sumList’:
Patterns not matched:
[]
(_:_:_)
Ok, modules loaded: Main.
*Main> sumList []
*** Exception: uebung1.lhs:(20,2)-(21,31): Non-exhaustive patterns in function sumList
*Main> sumList [3]
*** Exception: uebung1.lhs:(20,2)-(21,31): Non-exhaustive patterns in function sumListi i i i i
我做錯了什么? 我已經睡了一個晚上,但我只是不知道問題出在哪里。 受保護的等式應包含列表長度的所有情況。 感謝您的任何建議。
問題在於您的模式僅匹配具有一個元素的列表。
例如,如果您嘗試在ghci
定義一個函數:
a [x] = x
然后嘗試使用元素數量不同的列表來調用它:
a [1]
結果為1
a []
結果與以下Exception: <interactive>:5:1-13: Non-exhaustive patterns in function a
a [1,2]
結果,但Exception: <interactive>:1:1-9: Non-exhaustive patterns in function a
以下修改使您的功能正常運行:
sumList :: [Int] -> Int
sumList list | length list > 0 = list!!0 + sumList (drop 1 list)
| otherwise = 0
但是,當然,以下定義會更慣用和更有效:
sumList :: [Int] -> Int
sumList [] = 0
sumList (x:xs) = x + sumList xs
通過(x:xs)
模式,您會立即收到x
作為列表的頭( list!!0
)和xs
作為list!!0
的頭( drop 1 list
)。
該功能不適用於空白列表或包含多個項目的任何列表。
您的問題是,您要與[list]
匹配,這是一個成員為list
。 相反,請嘗試僅匹配list
。 這意味着它將與您類型簽名中類型為[Int]
任何內容匹配。
我很困惑,因為[a]
類型適用於任何長度的列表,但是[a]
僅匹配一個元素的列表。
我還附加了使用模式匹配編寫函數的另一種方法,希望對您有用。
sumList :: [Int] -> Int
sumList [] = 0
sumList (x:xs) = x + sumList xs
使用防護罩是很不尋常的,但是您做到了,您的代碼如下所示:
sumList :: [Int] -> Int
sumList list
| length list > 0 = head list + sumList (tail list)
| otherwise = 0
注意[list]
是如何由list
和!! 0
替換的!! 0
!! 0
替換為head
, drop 1
替換為tail
。
Hoogle是您的朋友!
您也可以將空列表的支票移至第一名警衛,如下所示:
sumList :: [Int] -> Int
sumList list
| list == [] = 0
| otherwise = head list + sumList (tail list)
請注意,此代碼與模式匹配代碼有多相似。
其他人已經回答了,但是我想強調一點,編譯器發出的警告指出了問題所在:
Pattern match(es) are non-exhaustive
In an equation for ‘sumList’:
Patterns not matched:
[]
(_:_:_)
這就是說該代碼在其模式匹配中未處理某些情況。 上面的空列表[]
被報告為不匹配,這意味着程序將在空列表上崩潰。 另外,格式(_:_:_)
的列表不匹配:這些列表至少包含兩個元素,例如1:2:rest
,這是一個從元素1
和2
並隨后進行列表rest
列表下一個元素。
因此,警告告訴我們,我們僅處理長度為1的列表。 實際上,我們只處理模式[_]
,它與_:[]
相同-列表從一個元素開始,然后到那里結束。
如果您是初學者,我認為您還沒有學習模式匹配。 這應該是您學習Haskell的優先事項:這是最重要的功能之一。 一般來說,如果您的遞歸代碼使用length, !!, tail, head
,則很可能您做錯了。 在某些地方需要這些功能,但在許多簡單的練習中卻不需要這些功能,模式匹配通常是足夠而優雅的。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.