C# Dictionary to F# Map

Following on from my past blog on effective parallelism I’ve continued digging into the functional language F#. I’m getting there – slowly and I am loving immutability. It’s quite a mindset change from my day-to-day work in imperative languages but I can see a little bit of progress in my functional thinking every day.

I’m doing quite a lot of C#->F#->C# interop (writing a distributed Erlang-like message passer, with agents using F#’s MailboxProcessor) and I came across a problem where I needed to convert a Dictionary produced in my C# layer to an immutable F# equivalent: Map.

Digging around online so far regarding F# is proving slow, it’s a new language, and there isn’t the plethora of code-snippets there are for other languages. The F# Manual also is nothing like MSDN – where code-snippets and examples are all over the place.

Anyway, here is a trivial little example of what I have come up with. I have an F# assembly, TestMap.dll, which exposes a module TestMap. A type in this module, ExampleDictionaryToMap, has a method Convert that takes a C# Dictionary and returns an F# immutable

The F# performing the conversion:


#light

module TestMap

open System.Collections.Generic

type ExampleDictionaryToMap =
  // Convert a C# Dictionary<string,int> to a Map<string,int>
  static member Convert(_dict: Dictionary<string, int>) =
     List.fold_left (fun acc idx -> Map.add idx _dict.[idx] acc) Map.empty (Seq.to_list _dict.Keys)

  // Convert a C# Dictionary<string,int> to a Map<string,int>
  // Steps are broken down:-
  //   (1) define an accumulator: function "accumulator"
  //   (2) define an initial value for the accumulator: "initialAccumulatorValue"
  //   (3) create the list to fold using Seq.to_list on the C# Dictionaries Keys emuerator: "list"
  static member StepByStepConvert(_dict: Dictionary<string, int>) =
     let accumulator acc idx = Map.add idx _dict.[idx] acc
     let initialAccumulatorValue = Map.empty
     let list = Seq.to_list _dict.Keys
     List.fold_left accumulator initialAccumulatorValue list

Then calling this F# from C#, Map is the F# type from Fsharp.Core:

Dictionary<string, int> csharpDictionary = new Dictionary<string,int>();
csharpDictionary.Add("value1", 1);
csharpDictionary.Add("value2", 2);
csharpDictionary.Add("value3", 3);
csharpDictionary.Add("value4", 4);

Map<string,int> fsharpMap = TestMap.ExampleDictionaryToMap.Convert(csharpDictionary);

I’m sure there is a more efficient way so any comments welcome!

Tags: , , ,

4 Responses to “C# Dictionary to F# Map”

  1. Brian McNamara Says:

    I think Map.of_seq is the simplest way to do the conversion; consider:

    #light

    open System.Collections.Generic
    let d = new Dictionary()
    d.["one"] <- 1
    d.["two"] <- 2
    d.["three"] seq)
    let m = keyValuePairs |> Seq.map (fun kvp -> (kvp.Key, kvp.Value)) |> Map.of_seq
    for kvp in m do
    printfn “%s -> %d” kvp.Key kvp.Value

  2. Brian McNamara Says:

    Looks like many angle brackets were swallowed… trying again

    #light

    open System.Collections.Generic
    let d = new Dictionary<string,int>()
    d.["one"] <- 1
    d.["two"] seq<_>)
    let m = keyValuePairs |> Seq.map (fun kvp -> (kvp.Key, kvp.Value)) |> Map.of_seq
    for kvp in m do
    printfn “%s -> %d” kvp.Key kvp.Value

  3. Brian McNamara Says:

    Looks like angle brackets were swallowed… trying again

    #light

    open System.Collections.Generic
    let d = new Dictionary<string,int>()
    d.["one"] <- 1
    d.["two"] <- 2
    d.["three"] <- 3
    let keyValuePairs = (d :> seq<_>)
    let m = keyValuePairs |> Seq.map (fun kvp -> (kvp.Key, kvp.Value)) |> Map.of_seq
    for kvp in m do
    printfn “%s -> %d” kvp.Key kvp.Value

  4. grahamsw Says:

    Tim, a quick hello from someone following much the same path, moving in a functional direction after many years in C/C++/C# land.

    I’ve found the process slow, and the learning curve painfully steep, but completely fascinating, and rewarding. There’s a dearth of good books, but if you have a solid grasp of the basics “F# for Scientists” is pretty good.

    A dictionary enumerates as a sequence of KeyValuePairs, so if d is the same Dictionary as above

    d |> Seq.fold_left (fun acc kvp -> acc.add kvp.Key kvp.Value) Map.empty

    is all you need.

    I’m translating “Programming Collective Intelligence”, a pretty damn interesting book on data analysis - something I’m sure you MMO guys are all over - into F# over at http://code.google.com/p/dataviz

    I don’t have much to show for it yet, but it’s powerful stuff. Take a look if your interested.

    http://cs.hubfs.net/ is also worth looking at if you haven’t already.

Leave a Reply