Creating a .NET Core 3.0 F# Console App
Tags: functional, fsharp, dotnet, tutorial
Published: 2019-09-30 00:19:16

This is part 1 in a new tutorial series on creating a genetic algorithm in F# and .NET Core 3.0.

## Learning Goals

This tutorial is focused on creating a new console application and learning some of the basics of F#. By the end of this tutorial you should be able to:

- Understand the basics of F#
- Create a new F# class library
- Create a new F# console application and link it to the class library
- Code a basic console input loop
- Code simple functions and classes in F#

## Prerequisites

Before starting, you will need to have [Visual Studio 2019](https://visualstudio.microsoft.com/vs/) installed (Community edition is free and fine for this purpose). You will also need to make sure the **.NET desktop development** workload in checked when installing Visual Studio.

## Understanding F Sharp

*Important Disclaimer: The author is an F# novice. I've read a few books and [written a neural net in F#](https://dev.to/integerman/neural-nets-in-c-vs-f-1322) as well as the code from this article series, but otherwise I am very new to the language. This represents my best attempt to share the knowledge I have learned, but does not constitute an authoritative 'best practice' type of model and may include inaccuracies based on incomplete understanding. Still, I want to share what I have learned*

F# is a functional programming language that is part of the .NET language family. 

The advantage of functional programming languages typically lies in application quality. F# handles nulls better by default and concepts such as discriminated unions and pattern matching make it harder to make mistakes.

Additionally, F#'s syntax is more concise than C#, meaning that it takes significantly fewer lines of code to express the same intent as it does in C# or other languages. Because you have fewer lines of code, it's harder for bugs to hide.

---

Because F# is part of .NET, it compiles down to IL and runs as part of .NET Framework and .NET Core. 

This means that other .NET languages such as C# and VB .NET can interact with F# libraries. This also means that you can mix functional programming and object-oriented programming based on the particular needs of what you're programming.

F# is also not strictly limited to functional programming as F# can be used to create traditional classes following .NET conventions (though the syntax is sometimes very ugly to do so).

## Understanding .NET Core 3.0 Console Apps

Console Applications are text-based utilities that run from the command line. They're typically used as part of automated processes or to integrate with other tools.

.NET Core 3.0 console apps operate cross-platform and are not strongly tied to Windows like .NET Framework console apps were.

In this tutorial series, the end result is not going to be a console application, but for the purposes of focusing on the code at first, we'll start with a console application for simplicity.

## The Application we'll Create

This is part one of a multi-part series on building a genetic algorithm in F#. The series will feature a 2D game board featuring a squirrel, a dog, an acorn, a tree, and a rabbit. As the series progresses, we'll talk more about what we'll simulate and how it will work as well as what genetic algorithms are.

For now, we'll create a simple console application that generates a game board with a Squirrel somewhere on it, then displays the game board to the user and allows them to regenerate a new game board at random.

![Console Application](https://thepracticaldev.s3.amazonaws.com/i/wp6nj19qzljt7p2svzcz.gif)

In order to do this we'll need:

- A `WorldPos` type that stores a 2D location in the game world
- A `Squirrel` class that inherits from an Actor class
- A `World` class that arranges the actors in the simulation
- A console application that displays the current `World` and prompts the user for input, repeating the loop until the user hits `X` to exit

Let's get started.

## Setting up the Solution

Our solution will contain two projects initially, a .NET Core console application and a .NET Standard class library. 

### Create the Console App

In Visual Studio, create a new project. In the new project wizard, change the `Language Type` drop down to F# and then look for the `Console App (.NET Core)` option as pictured below. Make sure that it lists F# as the language.

![New FSharp Console App](https://thepracticaldev.s3.amazonaws.com/i/4y2l9ra46pvq4sg9hsfc.png)

Click `Next`, name the project whatever you'd like. Whatever name you choose, I recommend you include the name 'ConsoleApp' somewhere in the name to help remember that this is the console application as we will have multiple projects.

### Create the .NET Standard Library

In Visual Studio, right click on the solution at the top of your solution explorer and choose `Add > New Project...`.

From there, select the F# Class Library (.NET Standard) option as pictured below.

![Class Library Project](https://thepracticaldev.s3.amazonaws.com/i/ls39fbjjtd6uz224ymrc.png)

Make sure that the option has F# specified as the language and that you select the .NET Standard option, not the .NET Core option. 

While .NET Core could work, the advantage of .NET Standard is that it can be referenced from a .NET Framework or .NET Core application. If you ever wanted to add a .NET Framework 4.8 application of some sort, you would be unable to reference a .NET Core class library. 

My general rule is that *unless I have a compelling reason not to, I will always create .NET Standard class libraries*.

Click next and name the class library whatever you'd like, then create it. I recommend ending the name of the library with Logic, Domain, or DomainLogic so that it's clear that this is a class library handling application logic. For the rest of this series, I will refer to this as the *domain logic library*.

### Reference the Class Library from the Console Application

Now that we have our two projects in the same solution, expand the console application in the solution explorer, right click on the `Dependencies` node, and click `Add Reference...`.

On the projects tab, check the box next to the domain logic library you created above and click Ok. This will allow your .NET Core console app to reference logic in the domain logic library.

## Adding the Domain Logic

Before we can implement the console application, we'll need to create the classes it references.

Note that in F#, the order of files inside of a project matters. F# will load files from top to bottom, so files at the top cannot reference values defined below them. Visual Studio lets you use alt and the arrow keys to move items up and down in the solution explorer and to add new items above or below an existing project.

The order we'll need for this application is:

1. WorldPos
2. Actors
3. World

![FSharp Class Library Ordering](https://thepracticaldev.s3.amazonaws.com/i/r5czpysj89k861lz9a01.png)

Go ahead and create empty F# script files named these things. You may delete or rename the default F# file that the class library starts with.

### WorldPos

In the WorldPos file, we'll add the following code:

```fsharp
namespace MattEland.FSharpGeneticAlgorithm.Logic

module WorldPos =

  type WorldPos = {X: int32; Y:int32}

  let newPos x y = {X = x; Y = y}
```

Here we're saying that everything belongs in the `MattEland.FSharpGeneticAlgorithm.Logic` namespace instead of in a root namespace. This helps keep things organized.

Next, we declare a module called `WorldPos`. This will allow other files to open (import) the logic we define here.

Next we define a simple type called `WorldPos` that consists of two integer values: X and Y. This compiles down as a simple class, but notice the syntax is incredibly minimal.

Finally, we define a function named `newPos` that takes in two parameters named `x` and `y`. This function will return a new object with an `X` and `Y` property.

Here's the interesting part: F# interprets return type as a `WorldPos` even though no explicit syntax exists declaring this. This is because there is nothing being imported via an open statement that could match the result of `newPos` besides the `WorldPos` type declared above. If there were, some additional type declarations would be explicitly necessary.

### Actors

Next let's look at the actors file:

```fsharp
namespace MattEland.FSharpGeneticAlgorithm.Logic

open MattEland.FSharpGeneticAlgorithm.Logic.WorldPos

module Actors =

  [<AbstractClass>]
  type Actor(pos: WorldPos) =
    member this.Pos = pos
    abstract member Character: char

  type Squirrel(pos: WorldPos, hasAcorn: bool) =
    inherit Actor(pos)
    member this.HasAcorn = hasAcorn
    override this.Character = 'S'

  let createSquirrel pos = new Squirrel(pos, false)
```

Like before, we're declaring a namespace and a module, but here we're opening another module, in this case the `WorldPos` module we defined earlier.

Next we define an abstract class called `Actor` and decorate it with an `AbstractClass` attribute telling F# that this type should be implemented abstractly. This style of syntax is frequently needed for object-oriented programming concepts.

We define a constructor on `Actor` that takes in a `WorldPos`. The class defines a `Pos` member that returns the `pos` argument from the constructor. Note that `Pos` is **not** implemented as a property and cannot be modified as F# values as defined immutable by default.

Next we define an abstract `Character` that will return a .NET `char` type.

---

The Squirrel type works similarly to Actor, but is not abstract. It explicitly inherits `Actor` and invokes its constructor. It exposes the `hasAcorn` parameter via the `HasAcorn` member, and then it overrides the `Character` value and represents the squirrel class with the `S` character.

*For those more familiar with F#, note that I'm choosing to work with abstract classes here instead of the F# concept of a discriminated union because it's easier to have sequences (F# collections) with different types sharing the same base class than it is to have sequences of different members of discriminated unions.*

---

Finally, we expose a `createSquirrel` function that creates a new `Squirrel` instance at the specified `pos`. It is defined without an acorn, which makes the squirrel sad.

### World

Okay, so now we're seeing some repetitive patterns in defining members. Let's do something a bit more complex.

```fsharp
namespace MattEland.FSharpGeneticAlgorithm.Logic

open System
open MattEland.FSharpGeneticAlgorithm.Logic.Actors
open MattEland.FSharpGeneticAlgorithm.Logic.WorldPos

module World =

  let getRandomPos(maxX:int32, maxY:int32, random: Random): WorldPos =
    let x = random.Next(maxX) + 1
    let y = random.Next(maxY) + 1
    newPos x y

  let generate (maxX:int32, maxY:int32, random: Random): Actor seq =
    let pos = getRandomPos(maxX, maxY, random)
    seq {
      yield createSquirrel pos
    }

  type World (maxX: int32, maxY: int32, random: Random) = 
    let actors = generate(maxX, maxY, random)
    member this.Actors = actors
    member this.MaxX = maxX
    member this.MaxY = maxY

    member this.GetCharacterAtCell(x, y) =
      let mutable char = '.'
      for actor in this.Actors do
        if actor.Pos.X = x && actor.Pos.Y = y then
          char <- actor.Character
      char
```

Here we start to see a few bits of new syntax.

`getRandomPos` is defined as a method (note the parentheses). This is important in this instance because otherwise F# will not re-evaluate the results of a call due to a process called *memoization*. Since we want to get a different random position every time, it's important to include these parentheses.

`getRandomPos` will declare `x` and `y` as results of the `System.Random` instance, holding on to a location within the game world.

Finally, `getRandomPos` will call `newPos` to build the position object. Because this is the last line in the method, its return `WorldPos` is returned by the method. Note that we do not use explicit `return` statements in F#.

---

`generate` exposes some new syntax. Instead of single result types, we're now working with *sequences*, an F# version of an immutable collection that can be iterated over. The `Actor seq` syntax indicates that the method will return a sequence of zero to many `Actor` instances.

Inside of the `generate` method we define a `seq { ... }` block. In this block we yield instances of that sequence. For now, we're only including a single Squirrel, but in future parts of this tutorial we will include a wider variety of objects.

---

Next we define the `World` class. This type manages the game board and arrangement of actors within it.

Note that inside of this type definition we declare an `actor` variable immediately, then expose that instance via the `Actors` member.

---

The `GetCharacterAtCell` method on `World` has some interesting syntax.

First, `char` is defined as a *mutable* variable, meaning that it can be assigned a new value to it after its initial assignment. This goes back to F# declaring things as immutable by default and viewing mutability as an anti-pattern to be minimized. The `char <- actor.Character` statement later will reassign`char` to hold the value to the right of the arrow.

Secondly, `for actor in this.Actors do` defines an F# for loop. Note that indentation governs the beginning and ending of the for block and no `end for` style syntax is necessary.

Thirdly, we see an example of F# conditional logic in the `if actor.Pos.X = x && actor.Pos.Y = y then` statement. This operates very similar to C# other than we do not have parentheses, we use a single `=` operator, and the `if` statement doesn't include an end-if, just like the `for` loop.

Finally, we end the method with a single `char` statement to load the `char` variable into memory and return it as the last statement in the method.

## Building the Console Application

Now that we can see a bit more of how F# logic flows, let's get the console application operational and play around with it.

This is a lot smaller than the domain logic library and will include a collection of helper functions related to dealing with console input and output and a function representing the main entry point in the application and user input loop.

### Display Functions

```fsharp
namespace MattEland.FSharpGeneticAlgorithm.ConsoleTestApp

open System
open MattEland.FSharpGeneticAlgorithm.Logic.World

module Display =

  let printCell char isLastCell =
    if isLastCell then
      printfn "%c" char
    else
      printf "%c" char

  let displayWorld (world: World) =
    printfn ""
    for y in 1..world.MaxX do
    for x in 1..world.MaxY do   
      let char = world.GetCharacterAtCell(x, y)
      printCell char (x = world.MaxX)

  let getUserInput(): ConsoleKeyInfo =
    printfn ""
    printfn "Press R to regenerate or X to exit"  
    Console.ReadKey(true)  
```

`printCell` is a simple function that will display `char` on the console. If `isLastCell` is true, then the `printfn` method will be used which includes a line break, otherwise `printf` will be used which will not move down to the next row. The `"%c" char` syntax formats the `char` character into the string.

`displayWorld` uses two nested for loops to loop row by row column by column through the game world by relying on the `MaxX` and `MaxY` properties on the `World`. From there it calls the logic we implemented earlier and then invokes the `printCell` method. Note that we enclose `x = world.MaxX` in parentheses in order to pass in the boolean result of that evaluation as the `isLastCell` parameter.

The `getUserInput` method (again, defined as a method to not memoize the results) prompts the user for input, grabs the first key from the keyboard, and returns the result of that call (since it's the last statement of the method).

### Main Input Loop

Okay, now the real meat and potatoes of the console application:

```fsharp
open System
open MattEland.FSharpGeneticAlgorithm.Logic.World
open MattEland.FSharpGeneticAlgorithm.ConsoleTestApp.Display

let generateWorld randomizer =
  new World(8, 8, randomizer)
  
[<EntryPoint>]
let main argv =
  printfn "F# Console Application Tutorial by Matt Eland"
  
  let randomizer = new Random()

  let mutable simulating: bool = true
  let mutable world = generateWorld(randomizer)

  while simulating do
    displayWorld world

    let key = getUserInput()
    
    Console.Clear()

    match key.Key with
    | ConsoleKey.X -> simulating <- false
    | ConsoleKey.R -> world <- generateWorld(randomizer)
    | _ -> printfn "Invalid input '%c'" key.KeyChar

  0 // return an integer exit code
```

In this final class of ours, we declare a `generateWorld` function to keep logic for creating a new `World` object in one place.

The `main` function is defined as the primary entry point of the application via the `EntryPoint` attribute.

Here we define some new variables needed for the core loop, declaring `simulating` and `world` as mutable as they can change inside the main application loop.

The `while simulating do` loop will repeatedly display the state of the world via the `displayWorld` function, then grab the user input via `getUserInput`, clear the console so that every iteration you only see the world's state.

Finally, we use `match` to effectively *switch* on the `key` that was pressed. The `| ... ->` syntax indicates a case to match, with logic to execute to the right of the `->`.

For example, when the `X` key is pressed, `simulating <- false` runs which sets `simulating` to `false`, causing the loop to terminate.

The `| _ ->` syntax indicates a *default* match - matching any case that was not otherwise matched explicitly. In this case, we use it to tell the user they entered something not expected / supported.

The final `0` statement tells the application to terminate and return 0 for a non-error exit code.

## The Finished Result

If you run the application, you should be prompted for input and be able to hit `R` to regenerate the world and see the position of the squirrel change, or `X` to exit the application.

![Console Application](https://thepracticaldev.s3.amazonaws.com/i/wp6nj19qzljt7p2svzcz.gif)

If you can't build or want to look at the source code, [check out the `article1` branch on GitHub](https://github.com/IntegerMan/FSharpGeneticAlgorithm/tree/article1).

## Next Up

[Next article](https://dev.to/integerman/f-squirrel-brains-adding-actors-and-getting-functional-o8o) I'll expand out the domain logic library to include the other actor types and turn the application into a mini-game where the player controls the squirrel. This will set us up for later articles where we will create a genetic algorithm and neural network to control the squirrel and display the simulation in something nicer than a text-based console application.

{% link https://dev.to/integerman/f-squirrel-brains-adding-actors-and-getting-functional-o8o %}