Interested in functional programming, I’ve always felt F# would be a good tool to have at my disposal considering there are a plethora of .NET-focused development companies around my area. Even though Microsoft focuses its efforts on C# , F# is an excellent and viable alternative for developing applications that target the .NET Core platform, opening hosting options to more than just Windows.
F# support is exposed directly in the new
dotnet CLI tool through the
--lang option flag which currently supports both C# and F#. Using the
dotnet new command, we can scaffold a barebones project to dip our feet in F# and .NET Core:
Once we have our project ready, seeing the result of our efforts is as easy as restoring the project’s dependencies with
dotnet restore and running
dotnet run which also causes
dotnet build to run:
Building and running the project
Rerunning the project without modifying the files will cause the built file to be re-executed without compiling:
Be sure to note above that
dotnet new creates the files in the current working directory. Let’s take a look at what comes of that command:
There’s not a lot going on there, so diving into each file won’t take long.
The sole code file contains a simple “Hello World” snippet for getting you going:
As alluded to in the file, Microsoft doesn’t spend too much time with detailed example, instead delegating any explanation of F# to fsharp.org.
The project’s configuration file is pretty standard for .NET Core applications (at least until Microsoft transitions to a MSBuild file once again), but there are a few F# specific items that are necessary to have everything hooked up properly:
Important point #1 is the inclusion of the F# compiler (
fsc) as a part of the tools section. This will bring in the compiler along with other NuGet packages when running
dotnet restore on the project.
Important point #2 to note are the additional build options to make use of the F# compiler, specifically the
buildOptions.compile properties. The
compilerName property needs to be set since the
dotnet CLI tool defaults to compiling C#. The
compile property (and
compile.includeFiles) needs to be set to tell the compiler which files are apart of the project and which order they should be loaded.
When looking for scaffolded projects more in line with what is offered through Visual Studio,
dotnet new isn’t going to cut it, and Visual Studio Code (and similar editors) aren’t going to have that functionality baked in by default. Luckily, there is a project scaffolding tool called Yeoman that has been adopted and used pretty much since the inception of .NET Core through the
generator-aspnet add-on, an open source project under the OmniSharp organization on Github. Microsoft itself even has documentation around building projects with Yeoman on its documentation site.
Installation is easy once Node.js and NPM are available:
and invoking the Yeoman generator is as simple as running
yo aspnet and answering some questions:
generator-aspnet contains both C# and F# projects, with the F# ones denoted in the selection interface with a suffix of
(F#), and all project templates contained within the generator are designed for .NET Core. There is another generator for F# projects,
generator-fsharp, but those projects are primarily focused on targeting .NET Framework, not .NET Core.
A project created with
yo aspnet will resemble a standard project layout much more closely, and those based on ASP.NET will have the same
Startup classes that their C#-based brethren contain.
More than a simple “Hello World” example, a project spun up with the ASP.NET Yeoman generator will get you going with the cross-platform Kestrel server that comes bundled with ASP.NET Core. This will allow for a consistent development and deployment experience across all .NET Core supported platforms, Windows, MacOS, and Linux.
Running the new ASP.NET project will use the same
dotnet run command but will add some new output during the program’s execution:
When hitting the project’s HTTP endpoint (which defaults to
http://localhost:5000), you’ll see the
Server: Kestrel header being sent in the response:
There should also be some new logging messages in the terminal with the application running:
I’ll count getting this far as a success, even though there hasn’t been enough code added to the project. That being said, I still need to take a further dive into both F# and .NET Core, and being a web-focused developer, I will most likely use ASP.NET to explore both of them. What I don’t currently like is how the types in the project are too object-oriented. Here’s the
ValuesController from our project:
Even though F# is a multi-paradigm language, defining object-oriented types in it always seems to go against its functional side, resulting in more verbose, less natural code.
Now, the F# project types available with the ASP.NET Yeoman generator are really just translations of the same project types available for C#, so these won’t always be inline with best practices of the F# community. If you’re interested in going further down the rabbit hole, F# projects like Suave, a simple web development library, are continuously improving their support for .NET Core, but at times, they will require some extra work to get going unless there are other templates that can be used to get your project off the ground.
The Suave team is working on bringing their project into the .NET Core limelight to make the process of using Suave and F# on .NET Core as easy as possible. Under their GitHub organization, they even have a sample project that can be used as a base for new applications. This will not use the ASP.NET Core Kestrel web server, but will instead use Suave’s own HTTP server implementation.
What I’ll end up tinkering with is finding a way to bring Suave’s HTTP routing combinators (example below) to ASP.NET and Kestrel, getting the best of both world’s: Suave’s F# native constructs and .NET Core’s level of support and progress on the Kestrel server.
Suave’s HTTP routing combinators
Update Jan 22, 2017: I’ve looked into this successfully and reported my experience with ASP.NET Core and Suave.
Even though progress is being made, there are still some short-comings that will hopefully be resolved as time goes on. F# is still second-class compared to C# and, to some extent, VB.NET in the .NET world, and .NET Core is no exception. C# is, and probably will always be, Microsoft’s golden child, so a lot of the .NET Core is stil geared towards C# developers. .NET Core tooling is relatively new and still progressing, so as the F# community puts effort, the gap between F# and C# support should being to close.