source: Alex Cullen, via FreeImages.com (FreeImages.com Content License)

My Path to F#

Brett Rowberry
8 min readDec 20, 2018

--

I love F#. How did I get here?

In my university studies, I went through what I assume was a traditional computer science program. It focused on ANSI C for Unix and added some Java for marketability and a touch of Lisp and Prolog to round things out (and a smidgeon of Python as well). I did it all on my trusty MacBook Air, and life was good.

During a Java internship in 2014, I learned a lot. That summer, Swift was announced, and there was a lot of buzz in the air. For my master’s project, I did an iOS project in Objective-C with OpenCV, but I couldn’t get Swift working with it. I graduated in the end of 2015. I read all 1000+ pages of the Swift Programming Language iBook, and I loved it.

I got my first job out of school programming in .NET on Windows, with really bad enterprise configuration, and I was disgruntled and sad. My wife told me to find something to love about work, so I could stop complaining. I tried to figure out how to get my hands on a Mac, get into iOS development, and all kinds of stuff. I couldn’t have predicted where my happy place would be.

One thing I did have going for me was a Pluralsight subscription. If I was going to be a C# developer, I was going to be a good one. I started watching C# courses, one after another. I think it was “Applying Functional Principles in C#” by Vladimir Khorikov that first introduced me to F#. It felt like a revelation. I’ve since watched every F# course on Pluralsight (there are only 11!).

I downloaded a PDF of Scott’s Wlaschin’s F# for Fun and Profit, read it entirely, about 2000 pages, and decided that I needed to start using this language!

My first opportunity to produce some F# code at work arrived. There was a crusty old app whose update lifecycle started with an Access DB maintained by a domain expert. First, somebody pumped the data from the Access DB to a development instance of an Oracle DB. Second, someone used that dev DB to update an acceptance Oracle DB. Third, a developer, like me, ran a C# project which pulled the data definitions from the acceptance Oracle DB. That data was used to generate code for a C# library to be used in a Windows desktop application as well as a C++ library that is embedded in the Oracle DBs. After those libraries were generated and deployed, the domain expert manually tested the C# library by spot checking some calculations in a desktop application that relied on the library (it is actually used in several applications, but that was the test harness). In addition, the domain expert ran queries against the Oracle DB to exercise the embedded C++ library. The main goal was to reduce the turnaround time from data definitions being updated in Access to having the C# library, C++ library, and Oracle DBs updated and automate as much of the process as possible.

Since the source of truth was Access (eww!) I started there. I had heard about F#’s amazing Type Providers in a Pluralsight course and was ready to try them out. Type Providers are F# libraries that you point to a data source. The Type Provider can then feed types to the compiler for you to code with. They’re basically a programming miracle. Here’s a little JSON sample:

open FSharp.Data//train the type provider with sample data
type Person = JsonProvider<""" { "name":"John", "age":94 } """>
//feed the real data to the trained type provider
let person = Person.Parse(""" { "name":"Tomas", "age":4 } """)
person.Name
person.Age

Person is an object with a property named Name of type string and a property named Age of type int.

I wanted to try SQLProvider to read Access, but reading an Access DB requires native drivers (which is unfortunate since SQL Server, Oracle, PostgreSQL, etc. don’t have that requirement) and I didn’t have control over the build servers at the time. However, Access exports nicely to XML. XML isn’t as hip as JSON, but it can do an incredible job of preserving type information. I didn’t ask for permission introducing F#, I just did it. My tech lead wasn’t happy, but it wasn’t a really high profile project either, so they let it slide. I used the XMLProvider from FSharp.Data — which is amazing. I had around 15 XML files that I really didn’t want to write bad parsers for, I was so excited. The data needed to be used in some C# assemblies and the types coming from the Type Provider wouldn’t cross over very well. So, I mapped the provided types from the XML files to records. I made one function for each file that returned an array with all the records. The process of manually creating the records and mapping them to the types generated by the type provider worked so well that I found errors in a weakly typed commercial data set, mostly null strings where they should have been required. They were subsequently fixed. Explicit Option types help you find data issues that nulls can’t. I even found some bugs in the C# codebase. Immutable records are good at exposing problems in a codebase where there is otherwise a lot of mutation because you now have something you can rely on never changing.

After getting the data via XML worked so well, our customer wanted to improve the testing workflow. The test data was already in Excel, and similarly to Access, I didn’t want to mess with drivers on the build server. So, we settled on exporting CSV files as the source of the test inputs and expected outputs. It was a thing of beauty. In addition, diffs in CSV show up well in version control. This improved codebase got a CI build for the first time in its over decade long existence. The build failed if the XML data was updated without the corresponsing CSV and vice versa. In addition, if a test failed, the failure messages included the test number, the input, the expected output, and the actual output. The domain expert could fix the data or test data himself if necessary, check in the updated files, and have the build run again. Only if that failed was more developer involvement required. By reducing handoffs, cutting out DB updates, and automatically testing the C# library that was previously tested manually inside of a desktop app, library update times were reduced by a few months. Now, those nearly 1000 tests run nightly and can be updated by a domain expert, no developer required. Score for F#!

When you deliver something good, people want more. The C# library had bullet-proof testing. However, testing of the C++ library called through Oracle functions was still manual. While it may have made sense to do unit testing on the C++ library, the intent was to test the library in the context of the database. Enter SQLProvider. It was the only solution I found for calling Oracle functions from .NET without just typing strings — Entity Framework understands procedures, but not functions. I got to use the same test data from the CSV files for this C++ library as I did for the C# one.

The project later progressed to the point that upon checkin of the XML and CSV files, the C# library was generated and tested. If that succeeded, the C++ library was generated and deployed to a database. If that testing succeeded as well, we knew we were ready for a full production deployment and database updates.

That same customer needed a console app to help make a lot of calls to evaluate a third-party app with a REST API. A little F# app I whipped together worked great. Next, they needed something to make some database calls. Same story. All of these efforts were done as a lone developer.

I haven’t deployed much more F# code to production, but it has been crucial for testing out some poorly documented REST APIs, inconsistencies between on-premise Active Directory and Azure Active Directory, and a myriad of other purposes. F# scripts and F# Interactive are awesome. And I can’t tell you how happy I am not writing PowerShell.

Have my teammates latched on to F#? Nope. I did get one to try C# Interactive, though. Baby steps. I took over an F# group on Yammer started by a contractor who left the company. I found one other F# user across the world in a completely different department. As luck would have it, they were due for a trip to the home office and helped me prepare my slides and live coding samples for a talk on F# I was giving. I was asked for an encore. Nobody contacted me afterwards to learn how to get started.

At some point, I started searching for a community instead of making one. I joined the F# Software Foundation. I learned about its mentorship program in 2017, but missed the application deadline. I applied in 2018. I was paired with an excellent mentor, Justin Hewlett. He works at Pluralsight. We had our first session right before I headed out to Open F#, getting to attend was another miracle. As luck would have it, Justin went as well. Small world.

The mentorship was great for solidifying my understanding of functional concepts like bind (aka flatMap), reduce, and fold. I had used reflection in C#, but this was the first time I had used it in F#. I learned about Quotations and Computation Expressions. I learned about Paket for package management and FAKE for build and task running. We built a sample web API with the Giraffe web framework. We discussed and prototyped a unit conversion library I’ve been thinking about for some time. We also tried out Visual Studio Live Share (which is great). While I had used git at work, this was the first time I collaborated with someone on GitHub.

At Open F#, I got to meet many of my heroes: Don Syme, Alfonso Garcia-Caro, Tomas Petricek, Mathias Brandewinder, Eugene Tolmachev, Stachu Korick, and Evelina Gabasova.

Don Syme and me at Open F# 2018. Photo by Author.

If you were trying to sell me on a programming language based on its community, I would have told you were crazy. Now I know that community is critical, and F# has a great one. When I have a question, I can always get a quick answer on Twitter or StackOverflow.

I’ve since given another F# talk at work. It was well received again, but the F# adoption needle hasn’t moved… yet.

This post is part of #FsAdvent 2018 organized by Sergey Tihon. Thanks, Sergey!

--

--