2017-05-24 86 views
3

我有以下類型:地圖在地圖上<'a, int>

type MultiSet<'a when 'a: comparison> = MSet of Map<'a, int> 

,我現在想聲明AF地圖功能對於這種類型的帶有簽名:

('a -> 'b) -> Multiset<'a> -> Multiset<'b> when 'a : comparison and 'b : comparison 

我曾嘗試:

let map m ms = 
    match ms with 
    | MSet s -> MSet (Map.map (fun key value -> m key) s) 

但它有簽名:

('a -> int) -> Multiset<'a> -> Multiset<'a> when 'a : comparison 

當我想要第一個提到的函數簽名時,我的實現有什麼問題?

回答

5

Map.map地圖,不是鍵。有充分的理由:它不能只是去插入映射的鍵而不是原來的鍵 - 它們可能不適合。哎呀,他們可能不是唯一的所有Map.map知道!

如果你想構建具有不同的鍵地圖,你必須把它拆開,作爲一個序列,將其轉換,然後從它構造另一個Map

let map m (MSet s) = 
    MSet (Map.ofSeq <| seq { for KeyValue (key, value) in s -> m key, value }) 

該實現你所需的簽名。

(也注意到你怎麼不要做match,您可以包括右參數聲明模式)

當心,這什麼也不實現用於驗證新密鑰:例如,如果它們變成非獨特的,有些計數將會丟失。我將這作爲練習給讀者。

+1

這是一個很好的答案。請注意,當多箇舊密鑰映射到同一個新密鑰(應該將計數加在一起,或者引發錯誤,還是保留任意值時,可能還需要考慮該怎麼做)。 – kvb

+0

這是一個很好的觀點。但我不想讓答案超載,只解決了眼前的問題。 –

+0

很好的答案,非常感謝。 – Alexander