[英]Indexing a Haskell data structure for queries
我有一個Dog
記錄的Data.Vector
,每個記錄都標識了所述狗所居住的House
。 我需要一個查找例程來查找屋子中所有隱約可見的狗,如下所示,但我需要進行恆定時間查找,而這是第一個版本所不能提供的。
dogs_by_houses dogs h = [ d | d <- Vec.toList dogs, h == house d ]
據我了解,優化Haskell代碼的一條中心規則是,編譯器僅在將其包含在lambda表達式內部后才計算每個表達式。 因此,在綁定h
之前,我必須在dogs_by_houses dogs
表達式內為此特定的dogs
構建一個查找表。
我認為Data.Vector
是完成此任務的最佳工具,盡管顯然您無法像使用C ++向量那樣縮小它們。 我大致實現如下:
dogs_by_houses :: Vec.Vector Dog -> Int -> [Dog]
dogs_by_houses dogs = let {
dog_house = house_id . house ;
v0 = Vec.replicate (maximum . map dog_house $ Vec.toList dogs) [] ;
f v d = let { h = dog_house d } in v // [(h,d:v!h)] ;
dbh = Vec.foldl' f v0 dogs
} in (dbh !)
在優化方面,這有什么愚蠢的選擇嗎? 我猜想像dbh
這樣的變量上的嚴格性標簽沒有太大幫助,因為按照定義,必須在dbh
有意義之前遍歷dogs
。
使用MVector
進行create
並折疊返回修改后的不可變矢量,這有什么大的優勢? 我所有的企圖使用MVector
和create
迄今出來絕不夠簡明,各層do
S或fold (>>)
同樣的結構或什么的。 我認為即使沒有顯式指定MVector
,編譯器也應該只在適當位置構建dbh
。
用列表無法實現該算法嗎? 您偶爾會看到人們建立無窮的素數的無限列表,然后選擇帶有primes !! n
的第n個素primes !! n
primes !! n
。 我假設以這種方式檢索第n個素數需要每次遍歷列表中的前n個素數。 相反,我注意到GHC將字符串存儲為C字符串,而不是列表。 編譯器會簡單地將已知列表元素表示為數組,而不是遍歷每個列表嗎?
我已經使用了Paul Johnson和Louis Wasserman的答案來構建以這種方式索引任意向量的函數,因為我必須基於幾個不同的索引函數來這樣做。
vector_indexer idx vec = \i -> (Vec.!) t i
where m = maximum $ map idx $ Vec.toList vec
t = Vec.accumulate (flip (:)) (Vec.replicate m [])
$ Vec.map (\v -> (idx v, v)) vec
dogs_by_houses = vector_indexer (house_id . house)
我尚未對此進行概要分析,但最終。 我希望有人必須編寫my_d_by_h = dogs_by_houses my_dogs
並調用my_d_by_h
才能從索引中受益。
我會用
Vec.accumulate (:) (Vec.replicate maxHouse [])
(Vec.map (\ d -> (dog_house d, d)) dogs)
它肯定會最多分配一個中間向量,我懷疑它可能很聰明,根本不分配任何中間向量。
我曾經被一個討厭的陷阱捉住了,做這樣的事情。 我使用Data.Map.Map作為查找表,但是原理是相同的。 我的函數獲取了一個鍵-值對列表,構造了一個Map,並返回了lookup函數。 它是這樣的:
makeTable :: [(Key, Value)] -> Key -> Value
makeTable pairs = ((fromList pairs) !)
對我來說似乎很明顯,我可以寫一些類似的東西
myTable = makeTable [("foo", fooValue), ("bar", barValue) ... and so on]
然后我可以說一個O(log N)查找
v = myTable "foo"
但是,GHC實際上所做的是從每個呼叫的列表中重建整個Map。 當您以這種方式創建部分應用程序時,GHC不會嘗試找出它可以從其獲取的參數中得出哪些值,它僅存儲原始參數並為每次調用完成整個功能。 完全合理的行為,但不是我想要的。
我必須寫的是:
makeTable pairs = \k -> table ! k
where table = fromList pairs
我想您將不得不做同樣的事情。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.