哈斯克爾支持一些基本的操作,通過列表遞歸,像head
,tail
,init
和last
。我在內部想知道Haskell如何表示其列表數據?如果它是單鏈表,那麼init
和last
操作可能會隨着列表的增長而變得昂貴。如果它是一個雙向鏈表,所有四種操作可以在一些內存爲代價進行O(1)
很容易,雖然。無論哪種方式,知道這一點很重要,所以我可以編寫適當的代碼。 (儘管函數式編程的精神似乎是「問它做什麼,而不是它如何做」)。Haskell列表的內部表示?
回答
列表,只表示爲......單鏈表。定義爲:
data [] a = [] | a : [a]
,你可以寫爲:
data List a = Empty | Cons a (List a)
內存佈局完全由這個定義。
- 構造函數是堆中分配
- 內部多態性字段是指向其他分配的節點
- 脊柱是懶惰
所以,你最終的東西是這樣的:
所以head
是O(1)這種結構,而last
或(++)
是O(n)的
沒有魔法在Haskell數據結構 - 其直接的定義,使其完全清楚的複雜性將是什麼(模懶惰)。如果你需要不同的複雜性,使用不同的結構(如IntMap,序列,HashMap中,矢量等)...
感謝您的回答。我不確定有必要強調這個答案應該是多麼明確/明顯 - 我是Haskell的初學者,而來自C這是一個巨大的變化,所以我仍然在計算一些東西。無論如何,再次感謝。 – 2013-02-25 09:38:21
哦,我並不是說它很「容易」,只是沒有魔法而已。如果您只是查看數據類型定義,則全是可導出的。 – 2013-02-25 11:08:26
兩大注意事項:**懶惰**和**融合**。懶惰意味着,例如,在'xs ++ ys'中,您只需支付追加的費用即可遍歷結果列表;頭(xs ++ ys)'是O(1),而不是O(n)。融合意味着許多操作不會超過遍歷的成本。例如'map(* 2)(xs ++ ys)'的成本低於'map(* 2)'和'++'的成本總和,因爲GHC消除了生成的中間列表。 – 2013-02-25 21:58:37
Haskell的列表被單獨聯繫,所以cons
,head
和tail
是O(1),同時init
和last
是O(Ñ)。
如果您需要更好的性能,請考慮使用來自Data.Sequence的Seq
類型,該類型提供對列表兩端的O(1)訪問權限。它在內部使用2-3 finger trees。
- 1. haskell列表內部拆分列表
- 2. Haskell列表內
- 3. 在Haskell列表中分割內部列表
- 4. Prolog的空列表內部表示
- 5. C# - 列表內部列表
- 6. 內部列表
- 7. 只替換haskell中的列表頭部?
- 8. Haskell的訪問元組數據的內部列表綜合
- 9. Haskell列表問題列表
- 10. Haskell中列表的乘法內容
- 11. Haskell-在列表
- 12. Parsec Haskell列表
- 13. haskell列表排列
- 14. Redis內部表示
- 15. 內部列表的實施列表
- 16. haskell中的列表排列
- 17. 列表的排列--Haskell
- 18. UML序列圖內部類表示
- 19. 在Haskell中擴展列表的列表
- 20. 列表haskell中的元組列表?
- 21. 類內部列表?
- 22. Retriving內部列表
- 23. 內部列表項
- 24. 對象的內部表示
- 25. Haskell - 操縱列表
- 26. 過濾列表Haskell
- 27. Haskell持久列表
- 28. Haskell - zip 2列表
- 29. typeof(T)的內部列表
- 30. 的Python:內部列表
「問做什麼的,它不是如何做它」不,如果你關心寫代碼,是相當快;) – 2013-02-25 10:11:35
那麼,這就是我認爲:-)因此,我的問題。 – 2013-02-25 10:36:09
「如果這是一個雙向鏈表,可以由所有四種操作O(1)很容易」其實,如果你想留下純粹的功能它不是那麼容易,所以普通的雙向鏈表沒有在Haskell使用多。在保持純功能的同時做所有的事情需要更復雜的數據結構 - 但事實證明,通過利用哈斯克爾的懶惰,你可以進一步研究_O_(1)操作(或者以某種方式分期_O_( _n_),這幾乎是一樣好)在它的單鏈式鏈表上比在任何程序語言中都是可能的。 – leftaroundabout 2013-02-25 19:59:44