An Introduction To FSharpx

The out-of-the-box F# language features and associated libraries are powerful and extensive. However, like any language, library or framework there are always areas for enhancement and/or simplification. This is where FSharpx comes in…

FSharpx (https://github.com/fsharp/fsharpx) is an open-source set of libraries that aims to provide a common set of functionality that extends or enhances various aspects of the out-of-the-box F# feature set. While FSharpx was founded by Ryan Riley and Mauricio Scheffer, it has had a number of contributors which makes it truly a community driven and community focused project. The library set provides features that allow you to more easily take advantage of the power of F# from C#/VB.NET projects, extend and enhance various F# features, and provide new functionality that is not otherwise available.

In this article, you’ll learn

  • how you can start taking advantage of FSharpx today.
  • about the various libraries that currently make up FSharpx
  • about some of the newer features that are currently in progress.
  • where to go for more information and how to get involved.

Let’s get cracking.

Getting Started With Core

The library known as FSharpx.Core was founded by the merging of two existing open-source projects—FSharp.Monad by Ryan Riley and FSharp.Core.CS by Mauricio Scheffer. Mauricio talks about this in his blog post entitled “Introducing FSharpx” which can be found at bit.ly/IntroducingFSharpx. With this knowledge in hand, you have probably guessed that FSharpx.Core focuses on providing various Monads (Computation Expressions in F# lingo) as well as on providing feature sets that improve the process of using F# functionality within C#/VB.NET.

The easiest way to get started with FSharpx is to install the FSharpx.Core NuGet package. This package pulls down all of the released FSharpx libraries (except FSharpx.TypeProviders) and adds appropriate references to your project. You can then interact with FSharpx.Core (or any of the other FSharpx libraries) in the same way that you would interact with any other .NET library. While there isn’t enough space in this article to provide examples (or even an adequate description) of each and every aspect of FSharpx.Core, we can look at a few key features.

Monads

Monads (a.k.a. Computation Expressions) have been in F# since version 1.9.2. A number of monads are provided out-of-the-box in F#--with async likely being the most well-known. Monads are a powerful “functional programming feature that can be used to manage data, control, and side effects in functional programs” (http://bit.ly/MsdnComputationalExpressions). FSharpx.Core provides several additional monads such as the Maybe Monad, State Monad, Reader Monad, Writer Monad, Undo Monad, Continuation Monad, and Distribution Monad.

There are quite a few examples of how to use these monads in various blog posts and in the unit tests of FSharpx. The following is an example of the Undo Monad—which was written by Steffen Forkmann.

module SimpleCalculator =
  let rec handleInput<'a> = undoable {    
      match Console.ReadLine() with         
      | "undo" -> let! _ = undo
                  ()
      | input -> match Double.TryParse input with
                 | true,x -> 
                   let! currentVal = getCurrent
                   do! putToHistory (currentVal + x)
                 | _ -> ()

      let! currentVal = getCurrent
      printfn "The current total is %O" currentVal
      return! handleInput }

SimpleCalculator.handleInput (empty 0.) |> ignore

The example above provides a simple calculator that only allows adding numbers. This code could easily be extended to handle any additional types of commands. Since this is using the Undo Monad, the last executed command can be reverted by simply typing “undo”. While this simple sample does not show it, the Undo Monad also supports “redo”.

Line two of the SimpleCalculator module initiates the use of the undoable monad. It then uses pattern matching to handle console input provided by the user. The first pattern, checks for input that matches the word “undo”. If that pattern matches, the last operation will be reverted. The second pattern will match any other input. When this pattern is matched, the input is evaluated to determine if it can be turned into a Double. If so, the provided value is added to the current value and placed in the history of commands. The astute observer may notice that this is using the State Monad under the covers to add the newly provided value to the existing total and add the new sum to the history. The last few lines of the module provide feedback to the user and recursively call handleInput.

Features For C#

Some of the founding principles for FSharpx were to make functional programming from C#/VB.NET easier as well as improve interoperability between C#/VB.NET and F#. Because of this, the developers of the project strive to make as much functionality as possible compatible with C#/VB.NET. In addition to providing F# test coverage, there is also a rich set of tests written in C# to ensure that this compatibility is always validated. Mauricio Scheffer has a great blog post at bit.ly/ReasonsForFSharpFromCSharp that talks about some of the features that have been added to FSharpx specifically to achieve this goal.

The following list includes a few of the extensions that have been added to improve this interoperability:

  • Conversion to/from Action/Func to F# Func
  • Basic pattern matching
  • Improved usage of F# discriminated unions from C#/VB.NET
  • Async extensions
  • Conversion to an F# Option, F# List, F# Set, and F# Map.

Additionally, many of the above mentioned extensions provide a wide variety of helper methods that make the use of F# features from C#/VB.NET more enjoyable, improve LINQ support, and provide features that would not otherwise exist. Additionally, FSharpx brings features that are only available in the latest versions of C#/VB.NET to older versions of these languages.

The following example shows one of the many extension methods provided by FSharpx for improving the use of the F# Option type from C#. This example converts the personName object to an F# Option. It then calls GetOrElse, which checks to see if the object is Some or None. If it’s Some, then the value is printed. If it’s None, then the provided “else” value is printed.

string personName = null;
var name1 = personName.ToFSharpOption().GetOrElse("Unknown");
Console.WriteLine("The person's name is {0}", name1);
personName = "Daniel Mohl";
var name2 = personName.ToFSharpOption().GetOrElse("Unknown");
Console.WriteLine("The person's name is {0}", name2);

Wait, There’s More

While FSharpx.Core was originally focused on the two categories that I’ve already described, it contains a lot more than just monads and helpers for C#/VB.NET to F# interoperability. Referring once again to Mauricio’s blog post (i.e. bit.ly/IntroducingFSharpx), you’ll see that the list of additional features covers everything from Collection and Option extensions to general functions that will make Haskellers feel more at home. Plus it’s open source, so if you don’t like something or feel that something is missing, all you have to do is send a pull request.

Looking Into FSharpx.AsyncExtensions

Another library that comes with the FSharpx.Core NuGet package is FSharpx.AsyncExtensions. Much of the code for this library was written by Tomas Petricek. If you’ve played with F# for very long, you’ve undoubtedly used asynchronous workflows. One of the core goals for FSharpx.AsyncExtensions is to add additional features to the existing F# asynchronous workflow functionality. The second primary focal area is to extend the MailboxProcessor functionality (which provides inter-process message passing similar to that provided Erlang). These two areas of F# are extremely powerful and the extensions provided in FSharpx make them even more so.

It’s long been known that asynchronous programming patterns can be used to make a solution scalable. Asynchronous workflows in F# have made this type of programming virtually trivial. The extensions to asynchronous workflows in FSharpx continue down this path by providing ways to improve performance, maximize fine-grained control, and increase the number of instances where asynchronous workflows can be used. For example, the AsyncSeq<’T> type provides asynchronous support for F# sequences. As another example, the Microsoft.FSharp.Control.Async type has been extended to include a Cache member. Additionally, extensions have been added to improve asynchronous support for System.IO.Stream, System.Net.HttpListener, and IObservable.

The F# MailboxProcessor (a.k.a. actor or agent) combined with asynchronous workflows allows for hundreds of thousands of lightweight, reactive agents to be spun up in a single process. These agents communicate via message passing, which allows for parallelism and concurrency. Don Syme talks about MailboxProcessor at bit.ly/MailboxProcessorIntro.

FSharpx.AsyncExtensions provides several enhancements and helpers for working with MailboxProcessors. First, a type alias is provided with the name Agent<’T>. This is a common alias used when creating actor or agent based solutions. Second, a series of types are provided for specific agent related use cases. The AutoCancelAgent type provides an agent that disposes itself when it’s no longer needed. The BatchProcessingAgent provides a mechanism for building up a queue of messages that are only published when a specific message count is reached or when the specified timeout value is reached. The BlockingQueueAgent provides an agent that implements the producer/consumer concurrent programming design pattern. Tomas Petricek has a great post about using the BlockingQueueAgent at bit.ly/BlockQueueAgent. The ConcurrentSetAgent provides a mechanism for keeping track of some state in the form of a Set. Tomas has a nice example of this in use at bit.ly/AgentBasedWebCrawler. Lastly, the SlidingWindowAgent allows for messages to be collected and emitted in overlapping groups of a specified size.

The following is a simple example of the BatchProcessingAgent in use. The first line of code creates the BatchProcessingAgent with a batch size of 5 and a timeout of 3000ms. The next two lines use a reactive programming technique to print some text every time a batch of 5 messages is published. The last two lines push a number of messages into the agent, so that the BatchProduced event will be triggered a number of times. You can find additional examples at bit.ly/BatchProcessingAgentExamples.

let agent = new BatchProcessingAgent<_>(5, 3000)

agent.BatchProduced 
|> Event.add (fun m -> printfn "Processing %s through %s" m.[0] m.[4])

for i in 1..100 do
  agent.Enqueue(sprintf "message %i" i)

Using the FSharpx.TypeProviders Library

The FSharpx.TypeProviders library was initially created by Steffen Forkmann. The primary goal of this library is to provide a collection of custom type providers. Since type providers are part of F# 3.0, you will need to install Visual Studio 11 as described at bit.ly/FSharp3Announcement. Additionally, if type providers are new to you, this blog post provides everything that you need to get started using the out-of-the-box type providers.

The easiest way to get the FSharpx.TypeProviders library is to install the FSharpx.TypeProviders NuGet package. Once you have installed the package, you’ll have the choice of a number of different custom type providers that have been created by a variety of different individuals. Examples include:

  • File System
    Allows strongly typed browsing of the file system.
  • App Settings
    Provides strongly typed retrieval of AppSettings values from a config file.
  • Mini CSV
    Allows strongly typed interaction with a comma-separated file.
  • Regex
    Provides a strongly typed interface to a regular expression.
  • Registry
    Allows strongly typed browsing of the Windows Registry.
  • XAML
    Allows strongly typed interaction with a XAML file.

Additionally, the library provides a handy DSL for creating these custom type providers.

The following is a simple example of how to use the File System type provider:

type T = FSharpx.FileSystemTyped< @"C:\Users\">
printfn "Path is %s" T.All_Users.Path

Checking Out the Rest

FSharpx is a continually evolving set of libraries. In fact, since I started writing this article, two new libraries have been added. In this last section, I’ll briefly explore these two new libraries and provide links to examples that will help you get started with them.

FSharpx.Stm

Software Transactional Memory (STM) is an approach for solving the concurrency problems associated with programming with shared state. The idea is that the subset of code that is to be executed atomically will optimistically attempt to proceed; however, if at any point the code is unable to proceed due to a shared state issue, the process will simply retry from the beginning. Gregory Neverov created a monad to bring this functionality to F#. You can read the blog that introduces this monad, provides a bit of background, and includes examples at bit.ly/StmForFSharp. In addition to the source for the STM monad, this library includes an ArrayQueue and ListQueue that are built on top of the STM monad. STM provides a solution to the shared state concurrency problem while also eliminating the need for developers to have to wrap a lot of code in lock statements; however, it comes at the cost of reduced performance.

FSharpx.Http

The FSharpx.Http library currently contains the functionality that was originally developed in a project known as FsConneg—an HTTP content negotiation library. The goal for this library is to continue to grow into a set of un-opinionated (as much as possible at least) set of building blocks that can be combined in various ways to create or extend web development stacks. You can find more information about FsConneg at bit.ly/IntroducingFsConneg and bit.ly/ContentNegotiationWithFsConneg.

Wrapping It Up

This article provides a high-level introduction to the various libraries that currently make up FSharpx. I think you’ll agree that there are many interesting and useful features that this open-source library provides. Additionally, the feature set is continually evolving and new versions of the libraries and NuGet packages are sure to appear frequently. FSharpx is intended to be the primary “go to” feature set used by the community to complement the existing F# libraries. You can find out more about FSharpx and/or contribute to the project by going to github.com/fsharp/fsharpx. The authors of the project love to receive feedback, feature requests, and additional contributions/contributors, so feel free to reach out!

You might also like...

Comments

Contribute

Why not write for us? Or you could submit an event or a user group in your area. Alternatively just tell us what you think!

Our tools

We've got automatic conversion tools to convert C# to VB.NET, VB.NET to C#. Also you can compress javascript and compress css and generate sql connection strings.

“The greatest performance improvement of all is when a system goes from not-working to working.” - John Ousterhout