How to write comparer for sorteddictionary?

Answered How to write comparer for sorteddictionary?

  • Saturday, May 12, 2012 4:10 AM
     
      Has Code

    i googled c# example and changed as following, not successful

    type SortComparer = //: IComparer<array<int>> =
        let Compare(x : array<int>, y : array<int>) : int =
            let mutable result : int = 0
            if x.[0] > y.[0] then
                result <- 1
            elif x.[0] = y.[0] then
                result <- 0
            else
                result <- 0
     
    // New DividePoly 
    // Dictionary<(int,int), Coeff)
    // Dictionary<(degree,degree), Coeff)
    let NewDividePoly(F : expr, G : expr) : expr =
        let mutable F_list = DictionaryToList(ExprToDictionary(F))
        let mutable G_list = DictionaryToList(ExprToDictionary(G))
        let mutable variable_list = getVariableList(F, G)
        
        let mutable FDict = new SortedDictionary<array<int>, double>(new SortComparer())
        let mutable GDict = new SortedDictionary<array<int>, double>(new SortComparer())
        //if variable_list.Count = 2 then
            
        for f_term in F_list do
            let mutable degree_list = Array.init variable_list.Count (fun x -> 0)
            for f_atom in f_term.Atom do
                match f_atom with
                | Atom(S,T,U) -> for i = 0 to variable_list.Count-1 do
                                    if variable_list.[i] = T then
                                        degree_list.[i] <- U
                                 Atom(S,T,U)
                | S -> S
            FDict.Add(degree_list,f_term.Coeff)
            
        for g_term in G_list do
            let mutable degree_list = Array.init variable_list.Count (fun x -> 0)
            for g_atom in g_term.Atom do
                match g_atom with
                | Atom(S,T,U) -> for i = 0 to variable_list.Count-1 do
                                    if variable_list.[i] = T then
                                        degree_list.[i] <- U
                                 Atom(S,T,U)
                | S -> S
            GDict.Add(degree_list,g_term.Coeff)


    Just would like to know who is reading my post every day

All Replies

  • Saturday, May 12, 2012 9:41 PM
     
     Answered Has Code

    This is really a question about implementing interfaces in F#, which comes with a well-known gotcha.

    F# implements interfaces explicitly by default (exactly the opposite of what happens in C#) and it currently has no way to implement interfaces implicitly. So, either you cast the object to the interface when you need the method, or you write a "forward method" that hides the casting from the caller.  So either of these:

    type SortComparer0() = // default explicit implementation interface IComparer<array<int>> with member x.Compare(a, b) = // int has a CompareTo method that returns what we want a.[0].CompareTo(b.[0])

    // cast explicit implementation let FDict = new SortedDictionary<array<int>, double>(new SortComparer0() :> IComparer<array<int>>)

    //------------------------------------------------------------------------------

    type SortComparer1() = interface IComparer<array<int>> with member x.Compare(a, b) = if a.[0] > b.[0] then 1 elif a.[0] = b.[0] then 0 else -1 // Forwarding method member x.Compare(a, b) = (x :> IComparer<array<int>>).Compare(a,b) let GDict = new SortedDictionary<array<int>, double>(new SortComparer1())

    Note also the simplification of the if/elif/else long-hand implementation -- expressions result in values directly; there's no need to have a value at a level any finer than the if expression.  In this case, as that is all there is to the function there's no need even to put that value into a named thing other than the function.  And certainly no need for any mutable named thing -- transcribing C# examples into F# needs to be done at a higher level than the individual tokens.

    • Marked As Answer by 沈世鈞 Wednesday, May 16, 2012 7:45 AM
    •