Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

F# -> Seq to Map

Tags:

f#

I'm trying to load all my Categories from the database and then map them to a Map (dictionary?), however when I use the following code:

[<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

it simply throws an error that says:

The struct, record or union type 'Category' has the 'StructuralComparison' attribute but the component type 'ResizeArray' does not satisfy the 'comparison' constraint

I have absolutely no clue about what to do, so any help is appreciated!

like image 879
ebb Avatar asked Apr 04 '11 19:04

ebb


2 Answers

F# is rightly complaining that ResizeArray<_> doesn't support structural comparison. ResizeArray<_> instances are mutable and don't support structural comparison, and you therefore can't use them as fields of records which are used as keys to Map<_,_>s (which are sorted by key). You have a few options:

  1. Have Tags use a collection type that does support structural comparison (such as an immutable Tag list).

  2. Use [<CustomComparison>] instead of [<StructuralComparison>], which requires implementing IComparable.

  3. Use a mutable dictionary (or another relevant collection type) instead of a Map. Try using the dict function instead of Map.ofSeq, for instance.

like image 144
kvb Avatar answered Oct 16 '22 08:10

kvb


The problem here is that by adding StructuralComparison attribute to the type Category you've asked F# to use structural comparison when comparing instances of Category. In short it will compare every member individually to see if they are equal to determine if two instances of Category are equal.

This puts an implicit constraint on every member of Category to themselves be comparable. The type ResizeArray<Tag> is generating an error because it's not comparable. This is true for most collection types.

In order to get rid of this error you'll need to make the ResizeArray<T> type comparable or choose a different key for the Map. Don has a great blog post that goes into this topic in depth and provides a number of different ways to achieve this. It's very much worth the read

  • http://blogs.msdn.com/b/dsyme/archive/2009/11/08/equality-and-comparison-constraints-in-f-1-9-7.aspx
like image 5
JaredPar Avatar answered Oct 16 '22 08:10

JaredPar