我有以下类型:
type MultiSet<'a when 'a: comparison> = MSet of Map<'a, int>
我现在想要使用签名声明此类型的af map函数:
('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
当我想要第一个提到的功能签名时,我的实现有什么问题?
答案 0 :(得分: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
,你可以在参数声明中包含模式)
请注意此实现不会对验证新密钥执行任何操作:例如,如果它们变为非唯一,则某些计数将丢失。我将此作为练习留给读者。