【问题标题】:Map on Map<'a, int>地图上的地图<'a, int>
【发布时间】:2017-05-24 15:38:18
【问题描述】:

我有以下类型:

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

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

【问题讨论】:

    标签: f# f#-interactive


    【解决方案1】:

    Map.map 映射值,而不是键。并且有充分的理由:它不能只是插入映射键而不是原始键 - 它们可能不适合。哎呀,它们甚至可能不是所有Map.map 知道的人都是独一无二的!

    如果你想用不同的键构建一个映射,你必须把它作为一个序列拆开,转换它,然后从中构造另一个Map:

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

    此实现具有您所需的签名。

    (另外,注意你不必这样做match,你可以在参数声明中包含模式)

    请注意,此实现对验证新密钥没有任何作用:例如,如果它们被证明是非唯一的,则会丢失一些计数。我把这个作为练习留给读者。

    【讨论】:

    • 这是一个很好的答案。请注意,当多个旧键映射到同一个新键时(应该将计数加在一起、引发错误还是保留任意值?),可能还值得考虑如何处理?
    • 这是一个很好的观点。但我不想让答案超载,只是解决了眼前的问题。
    猜你喜欢
    • 1970-01-01
    • 2018-04-17
    • 1970-01-01
    • 2011-02-09
    • 1970-01-01
    • 1970-01-01
    • 2011-10-30
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多