Map on map <'a, int>
I have the following type:
type MultiSet<'a when 'a: comparison> = MSet of Map<'a, int>
and now I want to declare af map function for this type with signature:
('a -> 'b) -> Multiset<'a> -> Multiset<'b> when 'a : comparison and 'b : comparison
I tried:
let map m ms = match ms with | MSet s -> MSet ( Map.map (fun key value -> m key) s )
But it has a signature:
('a -> int) -> Multiset<'a> -> Multiset<'a> when 'a : comparison
What happened to my implementation when I need the first mentioned function signature?
source share
Map.map
displays values, not keys. And with good reason: it can't just go and plug in the mapped keys instead of the original ones - they might not match. Heck, they might not even be unique to everyone Map.map
knows!
If you want to build a map with different keys, you have to disassemble it as a sequence, transform it, and then build more from it Map
:
let map m (MSet s) = MSet ( Map.ofSeq <| seq { for KeyValue (key, value) in s -> m key, value } )
This implementation has the required signature.
(also note how you don't need to do match
, you can include the template in the parameter declaration)
Beware that this implementation does nothing to validate new keys: for example, if they are not unique, some calculations will be lost. I leave this as an exercise for the reader.
source share