How to call F# code from C#

Functional Programming

 

 

 

 

 

Functional programming is popping up everywhere these days. Why? And should we care?

One reason we are seeing more of it is the explosion of interest in parallel processing. Computing clusters (for big data analysis), general purpose GPUs and multi-core processors all use parallel execution to deliver their performance benefits. Functional languages encourage the use of immutable data structures which, in turn, prevent a large class of errors—many of which appear when writing parallel code.

Other reasons for considering functional languages include:

  • powerful type inference systems that enable many common problems to be identified during development
  • the fact that many tasks, such as list processing and mathematical calculations, feel more natural in functional languages
  • support for ad hoc data analysis through interactive scripting
  • improving your development skills by coding in a different style
  • functional code can be easier to read as you specify what you want to happen, as opposed to how it should happen

Many languages have been extended to support functional programming—such as the addition of LINQ in .NET. While it’s possible to write functional C#, for example, a pure functional language (e.g. Haskell), or a predominately functional language (e.g. F#, Scala) will enforce/encourage a functional programming approach. It’s too easy to slip back into procedural code when using a predominately procedural language.

Many developers say they would like to try a functional language, but find it difficult to get started. Unless you are in a specialist field, such as machine learning or data science, it can be difficult to find an opportunity to program in one of these languages.

However, applications don’t have to be procedural or functional—they can be both. F# is a CLR language and Scala is a JVM language so it’s possible to use your favorite procedural enterprise language and throw in a little sprinkling of functional programming to brighten things up. You can start small and, as your confidence grows, move between procedural and functional languages based on your immediate needs.

Let’s see how we can use F# code in a C# application. I’m not going to attempt to teach you any F#—there are numerous resources for that. What I want to get across is how easy it is to start using a little F# in your day job.

Interop between C# and F

I’m going to discuss a simple C# console app that evaluates (scores) exams. The Visual Studio solution has three projects.

  • C# console app
  • C# domain model class library
  • F# evaluation library

Both the C# console app and the F# evaluation library reference the domain model library. The console app also references the F# library.

C# domain model class library

The domain model is as follows

public class Exam
{
    public ICollection<Section> Sections { get; set; }
}

public class Section
{
    public int Number { get; set; }

    public ICollection<Question> Questions { get; set; } 
} 

public class Question
{
    public Difficulty Difficulty { get; set; }

    public int Number { get; set; }

    public int Score { get; set; }
}

public enum Difficulty
{
    Easy,

    Hard
}

An Exam has numbered Sections which, in turn, contain numbered Questions, of varying Difficulty, and a Score.

F# evaluation library

Our F# project is called FSharpInterop.BusinessRules and it contains an Evaluations.fs file with the following preamble

namespace FSharpInterop.BusinessRules

module Evaluations = 

    open FSharpInterop.Domain

This defines an Evaluations module in the FSharpInterop.BusinessRules namespace. You’ll see how we use this to call our F# code later. We also open the domain model library so we have access to those types in our F# library.

The calculations we will perform in F# are

  • calculate the overall score
  • calculate a score for each section
  • calculate the score for each difficulty category (easy and hard)
  • retrieve all the easy questions

We’ll write a couple of helper functions to assist us. First, one that calculates the total score of a sequence of questions.

let private questionsScore (q: Question seq) =
    q 
    |> Seq.sumBy (fun x -> x.Score)

Next we’ll create a function to calculate the total score for a section. It makes use of questionsScore.

let private sectionScore (s: Section) =
    s.Questions 
    |> questionsScore

Notice that these are both private to the module.

Let’s return to the calculations that we’ll expose to our C# console app. Our function to calculate the overall exam score is

let overallScore (e: Exam) =
    e.Sections 
    |> Seq.sumBy sectionScore

The function to calculate scores for each section is

let sectionScores (e: Exam) =
    e.Sections
    |> Seq.map (fun x -> (x, x |> sectionScore))

To calculate scores grouped by question difficulty we use

let difficultyScores (e: Exam) =
    e.Sections
    |> Seq.collect (fun x -> x.Questions)
    |> Seq.groupBy (fun x -> x.Difficulty)
    |> Seq.map (fun (k, v) -> (k, v |> questionsScore))

Filtering to obtain the easy questions is performed by

let easyQuestions (e: Exam) =
    e.Sections
    |> Seq.collect (fun x -> x.Questions)
    |> Seq.filter (fun x -> x.Difficulty = Difficulty.Easy)

Notice that the F# functions are making use of our C# classes—without any fuss or ceremony.

That’s our F# module complete, so let’s see how we use it within our C# app.

C# console app

We’ve referenced the F# project in our console app project so just need to import the namespace.

using FSharpInterop.BusinessRules;

After retrieving an exam (e.g. from a database or web service), we can display its overall score using

Console.WriteLine("Overall score = {0}", Evaluations.overallScore(exam));

If you remember, Evaluations was the name of the F# module and overallScore was a function within that module.

The sectionScores function takes an exam and returns an IEnumerable<Tuple<Section, int>> list of sections and their scores. We can display these scores as follows

Evaluations.sectionScores(exam).ToList().ForEach(x => 
    Console.WriteLine("Section {0} score = {1}", x.Item1.Number, x.Item2));

The F# Seq collection corresponds to IEnumerable in C#. Visual Studio will display the types for you via Intellisense.

difficultyScores takes an exam and returns an IEnumerable<Tuple<Difficulty, int>> of scores for each level of difficulty. These scores are displayed using

Evaluations.difficultyScores(exam).ToList().ForEach(x => 
    Console.WriteLine("{0} questions score = {1}", x.Item1, x.Item2));

Finally, we retrieve and display all the easy questions as follows

Evaluations.easyQuestions(exam).ToList().ForEach(x => 
    Console.WriteLine("Question {0} is easy", x.Number));

Summary

I hope this article has given you some indication of how easy it is to start using F# in your day job. Pick some obvious quick wins—such as list processing or mathematical calculations (F# supports units of measure which can be invaluable in certain technical and scientific domains)—and dive in.

If you are interested in learning more about .NET, Learning Tree has a comprehensive curriculum of long and short .NET courses.

For those interested in the use of functional languages in data science, the Spark Machine Learning course gives a brief introduction to Scala and shows how it can be used within Spark to draw insights from big data.

The R programming language, popular in the statistics and data science communities, is functional at heart and is covered in Introduction to Data Science for Big Data Analytics and Introduction to R for Data Analytics.

image sources

  • Functional Programming2_Blog Image: Andrew Tait

Type to search blog.learningtree.com

Do you mean "" ?

Sorry, no results were found for your query.

Please check your spelling and try your search again.