2011-05-18 102 views
3

作爲初學者練習,我已經實現了以下功能找到的第n個元素的列表:Haskell代碼是否有效?

elem_at (h:_) 0 = h 
elem_at (_:t) n = elem_at t (n-1) 
elem_at _ _  = error "Index out of bounds" 

但是,如果我叫:elem_at [1,2,3,4] 5,它是否正確,只有在遍歷整個列表後纔會返回「索引超出範圍」,以便最後一行匹配模式_ _和[] 1?更一般地說,如果名單是不會是一個性能問題?可以以某種方式優化這種情況嗎?

回答

4

實際上,這正是索引列表的標準方法。您需要在檢查負數

elem_at xs n | n < 0 = error "elem_at: negative index" 

而且你可以添加一個特定的比賽爲空列表中添加:

elem_at [] _   = error "elem_at: index too large" 

和基礎和感性情況:

elem_at (x:_) 0   = x 
elem_at (_:xs) n   = elem_at xs (n-1) 

和你有列表索引的前奏定義,(!!)操作符。

通過工作包裝可以產生一個稍微高效的版本,將索引測試浮動到頂層。

+0

謝謝!這就說得通了。但是請等待......數學[] _,從[1,2,3,4]和5開始,我必須使用歸納情形4次,對不對? – Frank 2011-05-18 22:46:49

+0

如果n太大,您會遇到elem_at [] _的基本情況。這很好,因爲如果將n與長度進行比較,則最終遍歷列表一次以獲取長度,然後再次查找該元素。 – 2011-05-18 22:47:02

+0

@你說得對。補充問題:Haskell是否在內部存儲列表的長度,以便查詢它可能真的很快? – Frank 2011-05-18 22:49:08

2

我相信haskell的實現和遍歷任何語言的單鏈表一樣高效。如果數據存儲在不同的結構中,則可以在不遍歷列表的情況下回答問題。

+0

我的「問題」是我非常喜歡上面的代碼,因爲它非常簡潔。如果我可以寫更多的東西,並且在運行時仍然有非常高效的代碼,那將是理想的。我已經編寫了另一個版本,可以更快速地觸發錯誤(我認爲),但它並不優雅。 – Frank 2011-05-18 22:42:41

+0

如果您有一個靜態列表,並且您只想快速查找,則可以通過將列表轉換爲數組來獲得效率提升。 http://www.haskell.org/haskellwiki/Modern_array_libraries – 2011-05-18 22:45:37