[英]Procedurally generating large list of values in Haskell — most idiomatic approach? memory management?
[英]What's the most idiomatic approach to multi-index collections in Haskell?
在 C++ 和其他語言中,附加庫實現了多索引容器,例如Boost.Multiindex 。 也就是說,存儲一種類型的值但在這些值上維護多個不同索引的集合。 這些索引提供了不同的訪問方法和排序行為,例如 map、multimap、set、multiset、array 等。多索引容器的運行時復雜度通常是各個索引復雜度的總和。
Haskell 是否有等價物,還是人們自己創作? 具體來說,實現類型 T 的集合的最慣用方法是什么,它既具有索引的集合類型(T 是Ord
的實例)又具有索引的映射類型(假設 K 類型的鍵值可以明確地或通過 function T -> K
為每個 T 提供)?
我今天早上剛剛將 IxSet 上傳到 hackage,
http://hackage.haskell.org/package/ixset
ixset 提供了具有多個索引的集合。
ixset 作為 happstack-ixset 已經存在了很長時間。 此版本刪除了對任何特定於 happstack 的依賴項,並且是 IxSet 的新官方版本。
另一種選擇是 kdtree:
darcs 得到http://darcs.monoid.at/kdtree
kdtree 旨在通過提供更高的類型安全性和更好的時間和空間使用來改進 IxSet。 當前版本似乎在所有這三個方面都做得很好——但它還沒有准備好迎接黃金時段。 其他貢獻者將受到高度歡迎。
在每個元素都有一個始終可用的唯一鍵的簡單情況下,您可以使用Map
並提取鍵來查找元素。 在稍微不那么瑣碎的情況下,每個值只有一個可用的鍵,一個簡單的解決方案就是Map K (Set T)
。 直接查找元素將首先涉及提取鍵,索引Map
以找到共享該鍵的元素集,然后查找您想要的元素。
在大多數情況下,如果可以以上述方式直接完成某些事情(簡單的轉換和嵌套),那么這樣做可能是有意義的。 然而,由於顯而易見的原因,這些都不能很好地推廣到例如多個獨立的鍵或可能不可用的鍵。
除此之外,我不知道有任何廣泛使用的標准實現。 確實存在一些示例,例如來自 happstack 的 IxSet似乎大致符合要求。 我懷疑這里的一種適合大多數的解決方案可能會導致收益/復雜性比很差,因此人們傾向於自行推出以滿足特定需求。
直觀地說,這似乎是一個問題,它可能不是作為單個實現更好地工作,而是可以比Data.Map
允許更靈活地組合的原語集合,以創建臨時專用結構。 但這對於短期需求並沒有真正的幫助。
對於這個特定問題,您可以使用Bimap 。 不過,總的來說,我不知道有任何常見的 class 用於多映射或多索引容器。
我相信最簡單的方法就是使用 Data.Map。 盡管它被設計為使用單個索引,但當您多次插入相同的元素時,大多數編譯器(當然是 GHC)會將值放置到相同的位置。 多重映射的單獨實現不會那么有效,因為您想根據它們的索引查找元素,因此您不能天真地將每個元素與多個索引相關聯 - 例如[([key], value)]
- 因為這將是非常低效。
但是,我還沒有查看 Multimaps 的 Boost 實現,以確定是否有優化的方法。
我把問題說清楚了嗎? T 和 K 都有順序。 有一個 function key:: T -> K 但它不是order- preserving 。 希望管理 T 的集合,由 T 順序和 K 順序索引(用於快速訪問)。 更一般地,人們可能想要一組由一系列命令 key1::T -> K1, ..keyn::T -> Kn 索引的 T 元素集合,而這里的 key1 = id 恰好是這樣。 那是圖片嗎?
我想我同意 gereeter 的建議,即解決方案的基礎只是保持同步一堆(Map K1 T,.. Map Kn T)。 在 map 中插入鍵值對不會復制鍵和值,只分配在索引中正確位置創建新條目所需的額外堆。 在多個索引中插入相同的值,適當地鍵入,不應破壞共享(即使其中一個鍵是值)。 值得將結構包裝在 API 中,以確保對值的任何后續修改都計算一次並共享,而不是為索引中的每個條目重新計算。
底線:應該可以維護多個映射,確保共享值,即使鍵順序是分開的。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.