F# - > Seq to Map

时间:2011-04-04 19:31:09

标签: f#

我正在尝试从数据库中加载所有Categories,然后将它们映射到Map(字典?),但是当我使用以下代码时:

[<StructuralComparison>]
type Category = { 
    mutable Id: string; 
    Name: string; 
    SavePath: string;
    Tags: ResizeArray<Tag> }

let categories = session.Query<Category>() 
                    |> Seq.map(fun z -> (z,0)) 
                    |> Map.ofSeq

它只会抛出一个错误:

  

结构,记录或联合类型   '类别'有   'StructuralComparison'属性但是   组件类型'ResizeArray'   不满足'比较'   约束

我完全不知道该怎么做,所以感谢任何帮助!

2 个答案:

答案 0 :(得分:5)

此处的问题是,通过向StructuralComparison类型添加Category属性,您在比较Category的实例时要求F#使用结构比较。简而言之,它将逐个比较每个成员,看它们是否相等,以确定Category的两个实例是否相等。

这会对Category的每个成员施加一个隐式约束,使其自身具有可比性。类型ResizeArray<Tag>正在生成错误,因为它无法比较。大多数集合类型都是如此。

为了消除此错误,您需要使ResizeArray<T>类型具有可比性,或者为Map选择不同的密钥。 Don有一篇很棒的博客文章,深入探讨了这一主题,并提供了许多不同的方法来实现这一目标。这非常值得阅读

答案 1 :(得分:5)

F#正在抱怨ResizeArray<_>不支持结构比较。 ResizeArray<_>实例是可变的,不支持结构比较,因此您不能将它们用作记录字段,这些字段用作Map<_,_>的键(按键排序)。您有几个选择:

  1. Tags使用支持结构比较的集合类型(例如不可变Tag list)。

  2. 使用[<CustomComparison>]代替[<StructuralComparison>],这需要实施IComparable

  3. 使用可变字典(或其他相关集合类型)而不是Map。例如,尝试使用dict函数代替Map.ofSeq