簡體   English   中英

Haskell 中多索引 collections 最慣用的方法是什么?

[英]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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM