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

Map on Map<'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,您可以在参数声明中包含模式)

注意此实现对验证新密钥没有任何作用:例如,如果它们不是唯一的,一些计数将会丢失。我将其留作 reader.

的练习