地图在地图上<'a, int>

问题描述:

我有以下类型:地图在地图上<'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 

当我想要第一个提到的函数签名时,我的实现有什么问题?

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