2012-11-30 18 views
3

我有一個關於如何檢索Map的最小值的問題。最小值在一個地圖haskell

我有一個Map k (Maybe a,Maybe b)我需要檢索元組中第一個元素(最小的a)上的值最小的鍵,但找不到任何預定義的函數。有一些我可以使用的功能,或者我應該自己實現嗎? 謝謝

回答

5

您將需要約束Ord a。此外,您需要決定如何比較Just xNothing(因爲您必須將(Just x, y)(Nothing, z)進行比較)。我假設你想要Just x小於Nothing所有x。如果您使用toList將地圖轉換爲列表,則可以使用自定義比較功能在列表上使用minimumBy。此外,元組的第二部分(Maybe b)是無關緊要的,所以我們只需要考慮Map k (Maybe a, b)並獲得更一般的功能。

我建議是這樣

import qualified Data.Map as M 
import Data.List 

minimum' :: (Ord a) => M.Map k (Maybe a, b) -> k 
minimum' = fst . (minimumBy comp) . M.toList 
    where 
     comp (_, (Nothing, _)) (_, (Just _, _)) = GT 
     comp (_, (Just _, _)) (_, (Nothing, _)) = LT 
     comp (_, (Nothing, _)) (_, (Nothing, _)) = EQ 
     comp (_, (Just x, _)) (_, (Just y, _)) = compare x y 

這是很難說什麼樣的行爲,你真的想與問候到Nothing S,但另一種更合理的(*),替代將是最小的功能返回類型爲Maybe k,如果找到的最小元素(如上所示)爲(Nothing, _),則返回Nothing。達到此目的的一種方法是首先用toList返回filter列表以消除所有值爲(Nothing, _)的元素。

(*)讓Just x小於Nothing有點不好。當你尋找最大的元素時,你會希望的行爲與相反,所以它們都變得相當不穩定和醜陋。換句話說,當訂購類型a時,類型Maybe a只有部分有序(以自然的方式 - 當然,您可以強制執行總訂單,如上)。

+1

您可能想要考慮的另一件事是,如果元組的第一個元素相等,該怎麼做。在這種情況下,您可能需要使用第二個元素作爲決勝盤。 – mhwombat

+0

的確,但是這會引入'Ord b'約束,並且不清楚是否需要這種行爲。但絕對是需要考慮的一點。 – gspr

+0

@isturdy:我認爲當mhwombat說「元組的第一個元素」時,他意味着* value *元組的第一個元素,而不是鍵值元組中的鍵。 – gspr