2011-04-04 23 views
4

我試圖從數據庫中加載所有我Categories,然後將它們映射到Map,但是當我使用下面的代碼:F# - >序列,以地圖

[<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」 不滿足「比較」 約束

我完全不知道該怎麼做,所以任何幫助表示讚賞!

回答

5

F#是正確抱怨ResizeArray<_>不支持結構比較。 ResizeArray<_>實例是可變的並且不支持結構比較,因此您不能將它們用作用作Map<_,_> s(按鍵排序)的鍵的記錄字段。您有幾種選擇:

  1. Tags使用的是不支持結構比較集合類型(如一個不變Tag list)。

  2. 使用[<CustomComparison>]而不是[<StructuralComparison>],這需要執行IComparable

  3. 使用可變字典(或其他相關集合類型)而不是Map。例如,嘗試使用dict函數而不是Map.ofSeq

5

這裏的問題是,通過將StructuralComparison屬性添加到類型Category,您已經要求F#在比較Category的實例時使用結構比較。簡而言之,它將逐個比較每個成員,看它們是否相等以確定兩個實例Category是否相等。

這會對每個Category的成員隱含約束,以使它們自己具有可比性。 ResizeArray<Tag>類型由於無法比較而產生錯誤。大多數收集類型都是如此。

爲了擺脫此錯誤,您需要使ResizeArray<T>類型具有可比性,或爲Map選擇不同的密鑰。唐有一篇很好的博客文章深入討論了這個話題,並提供了許多不同的方法來實現這一點。這是非常值得讀