F# Basics – Result<'a>: or How I Learned to Stop Worrying and Love the Bind

This year, for FsAdvent, I’m taking a request and am going to write about embracing the happy path while writing F#. When coming to F# or other functional programming languages, one of the hurdles I see people face is often rethinking how they approach problems. While many posts talk about how to do this, I want to focus on one of the huge advantages – less worry and stress about the code working correctly.

For this post, I’m going to use a small example task – parsing a file on disk and summarizing some information from it. In this case, we’ll do something simple – read a CSV log file of “events” that occurred, and get the range of ID numbers from the file. Here is our input file:

Our task will be to read this file, parse it, and get the range of IDs being used. In this case, we’ll end up with 2 numbers as our result – 1928 and 1939.

When working in F#, I often start by describing the data I’ll be using, as well as the result I want to get or manipulate. Here, each row represents three things; a date, an ID, and a description of the event. We want to eventually get two numbers, a starting ID and an ending ID. In addition, we know there are a few things that could go wrong – the file might not exist, there might be no data in the file, or the data might be malformed. I’m going to start by defining a couple of types to help with this:

My goal when writing this utility will be to always write in a “happy path”. Instead of focusing on handling bad data or errors, I’m going to try to break everything up into small steps, each a function, that does one thing. I’m always going to assume my inputs are good, and my output will always either be good result or an Issue from above. Basically, I never want to think about “bad data” – I just want to write code that does something as I go.

In F#, there is a type that helps with this significantly – Result. The Result type is a discriminated union with two options; an Ok result, or an Error.

We’ll start by opening our file. In this case, we want a function that takes a filename and returns a Stream we can use for reading. File IO is one place where exception handling is nearly required, so I’m using that to create my error case:

This function will follow a common pattern – it takes an input (filename) and creates a Result: val openFile : filename:string -> Result

To parse the file, I’m going to use the CsvHelper library. This will allow me to not think about parsing the “hard parts” of CSV, like strings with embedded commas or quotes. Now we need a small function to take a stream from our openFile and convert it to a CsvReader:

Here, we know, if we have a valid stream, we’ll get a valid reader, so we can just write a simple Stream -> CsvReader helper. We can put these together with Result.map, which allows us to take an “Ok” result and use it’s value to make a new result.

Running in FSI, with a good filename, gives us val csv : Result = Ok CsvHelper.CsvReader. With a bad filename, you get:

val csv : Result =
Error
(IO
("Could not open file",
System.IO.FileNotFoundException: Could not find file

Now that our file is opened, we can move onto parsing. Again, we’ll assume we have a good input (our reader), and just write routines to just parse. In this case, I’m going to write a function to parse a single row and create an option, and a separate function to parse until we receive None, which will return our Result.

This does get a little uglier with the routine to read all of the rows. We want to make sure to close our file (we effectively pass ownership), so we need the try/finally to dispose of it anytime our routine to open succeeded. We’ll use a simple try/with to handle parsing errors. Using Seq.initInfinite and Seq.takeWhile allows us to “loop” through our data until we return None:

Our final step is to reduce the Event list to our two numbers:

Now that we have all of the pieces, we can stream these together. We will use two functions from the Result module in the core libraries to string these together – Result.map and Result.bind.

Whenever we have a function that doesn’t produce an error case, we will use map. When we have a function that takes our input and might need an error case, we will use bind. In our case, openFile and getIds both “always work” if their input are good, so we can map them. readRowsAndClose can map the data through to a list, but can also create an error case, so we will use bind. When stringing these together, we end up with:

When run via FSI, and given the input file above, this now produces:

val result : Result = Ok { Start = 1928
End = 1939 }

If we pass an invalid filename, we get a nice error:

val result : Result =
Error
(IO
("Could not open file",
System.IO.FileNotFoundException: Could not find file...

If we pass a good filename, but the file has bad data, that is also handled:

val result : Result =
Error
(DataMalformed
("Unable to parse data",
CsvHelper.TypeConversion.TypeConverterException: The conversion cannot be performed.
Text: '193d3'

By breaking this into pieces, and using Result.map and Result.bind, we were able to parse this in stages, where every stage could assume everything was “good”, and our errors propagate through cleanly at the end. Each step in the chain only has to focus on the task at hand.

Christmas Trees in WPF, 2016 Edition

Last year, I wrote about making Christmas Trees in WPF using FSharp.ViewModule.  At the time, I was excited being able to demonstrate how FSharp.ViewModule could make typical MVVM much more functional feeling.  This year, for my F# Advent Calendar contribution, I want to demonstrate how Gjallarhorn.Binding can serve as a replacement, and help create a WPF application with a design that is clean, functional, and most importantly, simple.

This post will modernize the Christmas Tree application from last year, improving it, and highlighting the differences between a classic MVVM approach to WPF and a more functional approach.  While reading through the post from last year would add context, it’s completely optional.

Read more

Christmas Trees in WPF using FSharp.ViewModule

As my contribution to the F# Advent Calendar this year, I thought I’d write a bit about one approach I often use to create WPF user interfaces in a functional style – mixing MailboxProcessor with FSharp.ViewModule.

This post will illustrate using a pair of MailboxProcessor instances mixed with FSharp.ViewModule to construct a simple application.  In the spirit of F# Advent, our application will be a small drawing application that allows us to place and decorate Christmas trees.

Read more

F# 2014 – A Retrospective and Call to Action

I have the privilege of being allowed to write the final post for the F# Advent Calendar in English. To celebrate, I thought I’d skip a technical post and end the year, and the Advent Calendar, with a brief, personal look back on 2014 and the wonderful time I’ve had within the F# community over this past year.

Read more

Slides and Code from “Using C#’s Async Effectively”

The slides and code from my talk on the new async language features in C# and VB.Net are now available on https://github.com/ReedCopsey/Effective-Async

Read more

Launching a WPF Window in a Separate Thread, Part 1

Typically, I strongly recommend keeping the user interface within an application’s main thread, and using multiple threads to move the actual “work” into background threads.  However, there are rare times when creating a separate, dedicated thread for a Window can be beneficial.  This is even acknowledged in the MSDN samples, such as the Multiple Windows, Multiple Threads* sample.  However, doing this correctly is difficult.  Even the referenced MSDN sample has major flaws, and will fail horribly in certain scenarios.  To ease this, I wrote a small class that alleviates some of the difficulties involved.

Read more

Setting useLegacyV2RuntimeActivationPolicy At Runtime

Version 4.0 of the .NET Framework included a new CLR which is almost entirely backwards compatible with the 2.0 version of the CLR.  However, by default, mixed-mode assemblies targeting .NET 3.5sp1 and earlier will fail to load in a .NET 4 application.  Fixing this requires setting useLegacyV2RuntimeActivationPolicy in your app.Config for the application.  While there are many good reasons for this decision, there are times when this is extremely frustrating, especially when writing a library.  As such, there are (rare) times when it would be beneficial to set this in code, at runtime, as well as verify that it’s running correctly prior to receiving a FileLoadException.

Read more

C# Performance Pitfall – Interop Scenarios Change the Rules

C# and .NET, overall, really do have fantastic performance in my opinion.  That being said, the performance characteristics dramatically differ from native programming, and take some relearning if you’re used to doing performance optimization in most other languages, especially C, C++, and similar.  However, there are times when revisiting tricks learned in native code play a critical role in performance optimization in C#.

I recently ran across a nasty scenario that illustrated to me how dangerous following any fixed rules for optimization can be…

Read more

Async CTP Refresh for Visual Studio 2010 SP1 Released

The Visual Studio team today released an update to the Visual Studio Async CTP which allows it to be used with Visual Studio SP1.  This new CTP includes some very nice new additions over the previous CTP.  The main highlights of this release include:

  • Compatibility with Visual Studio SP1
  • APIs for Windows Phone 7
  • Compatibility with non-English installations
  • Compatibility with Visual Studio Express Edition
  • More efficient Async methods due to a change in the API
  • Numerous bug fixes
  • New EULA which allows distribution in production environments
  • Anybody using the Async CTP should consider upgrading to the new version immediately.  For details, visit the Visual Studio Asynchronous Programming page on MSDN.

ConcurrentDictionary<TKey,TValue> used with Lazy<T>

In a recent thread on the MSDN forum for the TPL, Stephen Toub suggested mixing ConcurrentDictionary<T,U> with Lazy<T>.  This provides a fantastic model for creating a thread safe dictionary of values where the construction of the value type is expensive.  This is an incredibly useful pattern for many operations, such as value caches.

Read more

Next Page »