Getting started with F# and .NET Core
2017-07-24 21:10:00
TLDR: F# and .NET Core are really cool, you should give them a try.
I recently got interested in the .NET world thanks to my colleagues who are doing C# at $WORK. My last experience with Microsoft technologies was during my school years doing ASP Classic and it was not a great one but .NET Core is now a multi-platform, open-source .NET and it has a functional language: F#.
F# was designed by Don Syme. It’s open-source and maintained by the F# Software Foundation and individual contributors with some working at Microsoft.
I’m really fond of functional languages like Haskell or OCaml so I took F# for a test-drive to see what I could benefit from it.
Core vs Mono vs Standard
A bit of terminology first.
.NET Framework is Windows-only and is what you usually think about what .NET is.
Mono is a cross-platform implementation of .NET Framework from Xamarin (which Microsoft bought).
Microsoft chose to rewrite .NET to be truly cross-platform and stripped some APIs that were not considered core. The new product is .NET Core. So .NET Core is a smaller cross-platform .NET Framework.
.NET Standard aims to unify a set of APIs that all .NETs (Framework, Mono and Core) must implement.
.NET Native is a new initiative to compile code to native CPU instructions instead of using the CLR to compile to intermediate language.
Unfortunately resources for using F# with .NET Core are still very sparse, most examples are tailored for the .NET Framework or Mono so here are some notes on what I learned so far. Hope it helps.
Installation
First get .Net Core from here and follow installation instructions.
The basics
.NET Core provides a great command line tool: dotnet
.
Creating a new project:
λ mkdir project
λ cd project
λ dotnet new console -lang f#
Adding a package:
λ dotnet add package Newtonsoft.Json
Restoring (installing) packages:
λ dotnet restore
Building the app:
λ dotnet build
Running the app:
λ dotnet run
Publishing an app:
λ dotnet publish
Publishing with a specific framework and runtime:
λ dotnet publish --framework netcoreapp1.1 --runtime osx.10.11-x64
.NET Core projects used to have a project.json
configuration file but it’s been replaced by an XML file with a .fsproj
extension in order to gain better compatibility with MsBuild
.
Moving to this new format allows to build and restore multiple projects simultaneously thanks to solution files. A solution file is useful when you want to link projects together. When using dotnet restore
at the solution file level, all packages in that solution will be restored instead of having to do it for every one of them.
Adding a project to a solution:
λ dotnet sln todo.sln add todo-app/todo-app.fsproj
Tooling
There are a few additional tools you can use besides dotnet
CLI.
Paket
Paket is a dependency manager for .NET projects. It works with NuGet packages (like dotnet add packages) and also Git repositories references or HTTP resources. It seems to better solve dependency issues than the standard NuGet way.
It’s quite simple to add to your Core project. Download it for your platorm then paket init
will generate a paket.dependecies file. paket install
will install those dependencies.
Fake
Fake is F# Make. Similar to Rake in the Ruby world it’s a DSL you can use for all your build or deploy needs for example.
Ionide
Ionide is a Visual Studio Code/Atom package for F# development with everything you’d find in a modern IDE like syntax highlighting, autocompletion, type at point… Really an awesome package if you’re using these editors.
Omnisharp
For Emacs users like me, OmniSharp is a cross-platform tool that brings Intellisense for a lot of editors (Emacs, Vim, Sublime…). Combined with fsharp-mode
this makes a pretty nice development environment.
Forge
Forge is a project/solution management tool. It’s useful for creating a project without an IDE but it seems it’s not needed for .NET Core projects. If you’re working on a Mono project this is a nice addition to your toolbelt.
Web stuff
In C# you would usually use ASP.NET Core (aka Rails.NET) or eventually Nancy a Sinatra-like framework for your web services needs. It’s possible to use them with F# but a better alternative exists: Suave.
Tamizh Vendan has written a good book on Suave: F# Applied.
F# the language
F# looks a lot like OCaml with a few goodies. I’m not going to detail the syntax, just highlight some features of the language that I really like.
Go check F# syntax in 60 seconds for a quick overview of the syntax.
Use C# libs
One of the best benefits of using F# is the amount of quality .NET libraries available. Most of these are written in C# but you can use them in F# quite easily.
Since it’s my first attempt to learn .NET programming, I found that learning a bit of C# can be helpful to understand how to use libraries and stuff. The C# 7 and .NET Core: Modern Cross-Platform Development book was an easy read and simple enough approach to learn more about the ecosystem.
Smooth Operators
The pipe operator |>
(that Elixir borrowed from F#) lets you pass the result of the function on the left onto the other function as its first argument.
Note: the F# REPL is launched with fsharpi
, ;;
are needed to end statements in the REPL.
> [1..10] |> List.filter (fun n -> n % 2 = 0);;
val it : int list = [2; 4; 6; 8; 10]
<|
takes the function on the left and applies it to the value on the right.
> let double n = n * 2;;
val double : n:int -> int
> printfn "The double of 16 is %d" <| double 16;;
The double of 16 is 32
val it : unit = ()
The composition operator >>
lets you ‘compose’ functions together.
Let’s define two functions triple
and square
:
> let triple n = n * 3;;
val double : n:int -> int
> let square n = n * n;;
val square : n:int -> int
We can compose the two functions like:
> let tripleSquare = triple >> square;;
val tripleSquare : (int -> int)
> tripleSquare 2;;
val it : int = 36
The <<
operator takes two functions and applies the function on the right before the one the left of the operator.
> let isOdd n = n % 2 = 1;;
val isOdd : n:int -> bool
> [1..10] |> List.filter (not << isOdd);;
val it : int list = [2; 4; 6; 8; 10]
Async and Parallel
Asynchronous workflows can be easily constructed using async { ... }
. It’s also possible to have some computations composed in parallel using the fork-join
combinator Async.Parallel
.
let task1 = async {
do! Async.Sleep 1000
printfn "task1 finished!"
return 5
}
let task2 = async {
do! Async.Sleep 500
printfn "task2 finished!"
return 2
}
[task1; task2]
|> Async.Parallel
|> Async.RunSynchronously
|> printfn "%A"
outputs:
task2 finished!
task1 finished!
[|5; 2|]
val task1 : Async<int>
val task2 : Async<int>
val it : unit = ()
This example executes both async tasks task1
and task2
concurrently and wait for both to finish before printing the results.
Mailboxes
Another concurrency primitive available in F# is mailboxes. F# can natively handle message-based concurrency thanks to its mailbox processors. It somewhat brings Erlang’s actor model to F#.
Basically actors are lightweight constructs that have a queue and can send messages to other actors and process incoming messages sent to them from the queue.
This great article by Rachel Reese explores the subject if you want to dig deeper.
Some additional resources
It’s quite hard to find good resources updated for .NET Core with examples so I’ve setup a Github Repository with some basic tasks I needed to do like using a database or parsing JSON. I’ll try to update it whenever I manage to do something that was difficult to find existing resources for.
There is a really friendly Slack that you should join.
F# for fun and profit is a superb collection of resources on F#. There is an ebook compiling all the posts too.
This Awesome dotnet core repo lists some libs, tools and resources for development with .NET Core but not specifically F#.
Regarding books Expert F# is great and assumes no prior .NET knowledge.
Ody Mbegbu has made a nice intro video to getting started with .NET Core using F#.
Conclusion
F# is a nicely designed functional language (that can do OOP too but I didn’t try it yet). Most of the resources are newbie friendly and avoid words like functors
and monads
. In general I find them more geared toward practical usage which is pretty nice sometimes.
The main issue with .NET Core at the moment (1.x) is that there are still a lot of missing APIs which lead to incompatible libraries like FSharp.Data but the good news is that the upcoming .NET Core release later this year (2.x) will bring something like 20000 more APIs and most of the libs should be compatible or easily adaptable then.
For me F# is a great language with a robust eco-system. It has all the FP features that matters the most to me: a strong type system, pattern-matching and good concurrency primitives. Its interoperability with C# could be a gateway to more functional programming in my company. I’m currently rewriting some of our slow Ruby services with it and I wish this will demonstrate its value to my co-workers.
Hope this article helped clearing up a bit how to work with F# and .NET Core. Don’t hesitate to post your questions or remarks here.