F# + C# = .net#

If you wondering about how to join two languages like F# and C# into the one consolidated solution, then I can show you how do that easily.

Beginning from Visual Studio 2010, F# is native language for the Microsoft IDE. It means, from the start of work with VS you could easily use F# with full (nearly full;) But we should back to our main topic …

While you have new solution with C# project, then you could as a normal C# project, a new F# project like below:

So far so simply. Then, as usual we need to add reference for new F# library to our existing C# project, and that’s really all. We could use in C# any already prepared F# code, and vice versa, we only need to revert dependencies between them.

Now, I will show an example of this idea.

Problem description: we have a description of employees in some different format. We need transform them to one consistent structure.

C# project: console application which will use translation code from F# to process input loaded by C# code, and then it will print the results.

F# project: set of functions (library) for translation of different source formats to one consistent structure for Employee.

So, whole C# code you can see below:

using System;
using Translation;

namespace PersonSourceTranslation
{
    internal class Program
    {
        private static void Main()
        {
            const string textSource = "jacek;26";
            var firstPerson = Translate(textSource, From.Text, Types.ToPerson);
            Console.WriteLine(firstPerson);

            const string anotherTextSource = "Julia,2";
            var secondPerson = Translate(anotherTextSource, From.Text, Types.ToPerson);
            Console.WriteLine(secondPerson);

            const string xmlSource = @"30Marcin";
            var xmlPerson = Translate(xmlSource, From.Xml, Types.ToPerson);
            Console.WriteLine(xmlPerson);
        }

        private static Types.Person Translate(string textSource,
                                              Func> extract,
                                              Func translate)
        {
            var personTuple = extract(textSource);
            return translate(personTuple.Item1, personTuple.Item2);
        }
    }
}

Okay, what we have there? There are three similar parts. Definition of source (text file, fields separated by semicolon; text file, fields separated by comma; xml file), invocation of Translate function where we put references to two functions written in F# (detailed explanation for them later), and finally there is a print statement. This code has one static method definition too, which was already mentioned, Translate. As a result it uses type declared in F# code (Types.Person) which is our common definition of employee structure. What we are doing here is: extracting from text source the tuple with person’s data, which is done by one of the two methods: From.Text and From.Xml. Then we are simply translating tuple into Types.Person object which has ToString() method, which allows us to see the content of this object. For translation purposes we are using Types.ToPerson method, which is F# code too. The results for this code are:

Name: jacek, Age: 26
Name: Julia, Age: 2
Name: Magda, Age: 24

Now, we can take a look into F# code.

module Translation.Types

open System

type Person(name, age:string) =
    member this.Name = name
    member this.Age = Convert.ToInt32(age)

    override this.ToString() =
        sprintf "Name: %s, Age: %d" this.Name this.Age

let ToPerson name age =
    Person(name, age)

This code contains our definition of Types.Person class. Any type declared in F# is by default immutable type. What we have there is definition of ‘private’ fields, name and age and definitions of getters for them. Additionally, we overriding the ToString() method to have a better view of object in the string form.

Finally, there is ToPerson(…) method which we are using in C# code to translate data from tuple to a Person object.

module Translation.From

open System.IO
open System.Xml.Linq
open Microsoft.VisualBasic.FileIO

let AsStringReader' input =
    new StringReader(input)

let ElementValue'(document:XDocument, elementName) =
    document.Root.Element(XName.Get(elementName)).Value

let Xml(input:string) =
    let document = XDocument.Load(AsStringReader' input)
    let name = ElementValue'(document, "Name")
    let age = ElementValue'(document, "Age")
    (name, age)

let Text(input:string) =
    let csvParser = new TextFieldParser(AsStringReader' input)
    csvParser.Delimiters  <- [| ";"; ","; "\t" |]
    let row = csvParser.ReadFields()
    (row.[0], row.[1])

Here is the final part (of  course the most important;) of our project. We can start with analyzing two ‘private’ methods with ‘ in the name. It is really simple trick to do a method not accessible from C# code and still available from F# code. AsStringReader’ methods it is just better form of StringReader constructor to improve a readability of this code. ElementValue’ method has code for extracting value for a given name from the xml document.

Finally, we have two methods which are used to extraction in our C# code. Xml methods is using XDocument class to load a xml document and extract needed data from it, and then it returns data as a tuple and that’s all. The second method, Text is using class TextFieldParser from referenced library Microsoft.VisualBasic (yes yes, it is library written in Visual Basic, or rather .net version of that ;). This class is designed for dealing with CSV like files. We are defining delimiters, then we could read fields from any files which is covered by that. On the end of the code, as before we are returning the tuple with data.

That’s all and as I said, it is not a big deal to have two languages like F# and C# working for us to have one consistent application or library.
Whole solution(save file as -> then change extension of the file from jpg to zip, then simply unzip it):

project

Advertisements

2 thoughts on “F# + C# = .net#

  1. There is no need to use any member variables. You can simplify the Person class as follows …

    type Person(name, age:string) =
    member this.Name = name
    member this.Age = Convert.ToInt32(age)

    override this.ToString() =
    sprintf “Name: %s, Age: %d” this.Name this.Age

  2. No need to use member variables in the Person class. Can write the Person class as …

    type Person(name, age:string) =
    member this.Name = name
    member this.Age = Convert.ToInt32(age)

    override this.ToString() =
    sprintf “Name: %s, Age: %d” this.Name this.Age

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s