Impeachment in a functional way

Functional Programming (FP) did not really click with me until I saw how it utilizes composition of functions to model pipelines of tasks. Lots of sources on the internet mention immutability and algebraic types as great advantages of FP but it was composition that won me over.

In particular, composition is perfect for describing workflows from the real world.

The impeachment process

I came across such a real world workflow in this article on Axios. The process for impeachment and removal from office goes through a number of steps where each step has two possible outcomes: Either the process terminates or it continues.

The steps are:

  1. Investigation in the House
  2. House vote
  3. Senate trial

Our goal is to model the steps in a way that mimics the terminations and continuations of the process. We also want each step to report the reason for a termination.

The non-functional way

In a non-functional language such as C# there are a number of ways you could model the process. One way would be to let each step throw an exception in case the process should be terminated. In that case the overall code would look something like this:

public void RunImpeachmentProcess()
{
    try
    {
        InvestigateInHouse();
        VoteInHouse();
        TryInSenate();
    }
    catch (Exception ex)
    {
        Log($"The impeachment process stopped: {ex.Message}.");
        throw;
    }
}

It works but it is not very elegant. Exceptions are for exceptional cases and stopping an impeachment process is not exceptional and this way is not very explicit.

Another way would be to let each function return false or true indicating termination or not.

public bool TryRunImpeachmentProcess(out string reason)
{
    if (TryInvestigateInHouse(out reason))
    {
        if (TryVoteInHouse(out reason))
        {
            return TryTrialInSenate(out reason);
        }    
    }

    return false;
}

This also works and it does not look too bad. However, if the number of steps increase above three it will end up as a mess that is hard to follow. There are other variations, for example you could mix in return statements to avoid the triangle of nested if-statement. You may also have to pass information from one step to the next as a parameter which only makes it harder and messier.

The functional way

Enter composition. With composition your code could look something like this (I will be using F#):

let runImpeachmentProcess =
    investigateInHouse
    >=> voteInHouse
    >=> tryInSenate

This is very explicit. The workflow is self-documenting and you can easily see the steps involved.

Let’s see what the implementation looks like. We start with a type that holds the result for a step, whether the process continues or terminates:

type Reason = Reason of string

type ImpeachmentResult<'T> =
| Impeach of ImpeachValue:'T
| DontImpeach of Reason 

We could have used the built-in Result type that can be either Ok or Error. Depending on your political standpoint, using Error for ending the impeachment process may not be the correct term so I created my own ImpeachmentResult type.

We now add the >=> (fish-)operator for composing two functions that each return an ImpeachmentResult:

let (>=>) a b x =
    match a x with
    | Impeach v -> b v
    | DontImpeach reason -> DontImpeach(reason)

The operator takes two functions, a and b with the following signatures:

a:'a -> ImpeachmentResult<'b>
b:'b -> ImpeachmentResult<'c>

Hence, the >=> unwraps the impeachment result of function a and feeds it into function b. The parameter x can be of any type and it does not have to be the same type for each step. I.e. each step may return different results. The only requirement is that the next function takes the same type as parameter.

Let’s add dummy implementations for the three steps (I’ll leave the actual implementation as an exercise for the reader). I have added a exitAtparameter of type ExitAtStep to each function to control which step the process should exit at. In the real world you won’t need such a parameter. However, it does show that you can pass parameters from on step to the next, all handled by the >=>operator:

type ExitAtStep =
| None
| Investigation
| Vote
| Trial

let investigateInHouse exitAt = 
    match exitAt with
    | Investigation -> DontImpeach (Reason "Investigation did not find enough evidence")
    | _ -> Impeach exitAt

let voteInHouse exitAt =
    match exitAt with
    | Vote -> DontImpeach (Reason "Less than two-thirds voted for impeachment in House")
    | _ -> Impeach exitAt

let tryInSenate exitAt =
    match exitAt with
    | Trial -> DontImpeach (Reason "Senate trial exonerated the President")
    | _ -> Impeach exitAt

Finally, we get to the workflow function that is a composition of the three steps above:

let runImpeachmentProcess =
    investigateInHouse
    >=> voteInHouse
    >=> tryInSenate

Note that for this example runImpeachmentProcess is a function of type:

runImpeachmentProcess:ExitAtStep -> ImpeachmentResult<ExitAtStep>

Let’s run it:

let run exitAt =
    let result = runImpeachmentProcess exitAt

    match result with
    | Impeach _ -> printfn "Remove from office."
    | DontImpeach (Reason reason) -> printfn "No impeachment for the following reason: %s." reason

If all three steps return Impeach, it will print out “Remove from office”. If at least one of the three steps return DontImpeach, the code will print out the reason for the exited process with the reason for the first function that returns DontImpeach. Subsequent steps will not be called if one returns DontImpeach. Let’s have a look at the output:

run None
// Remove from office.

run Investigation
// No impeachment for the following reason: Investigation did not find enough evidence.

run Vote
// No impeachment for the following reason: Less than two-thirds voted for impeachment in House.

run Trial
// No impeachment for the following reason: Senate trial exonerated the President.

Closing

Composition gives us a very strong tool for creating explicit workflows for our processes. We are able to create a function composed of other functions that each represent a step in the workflow. The code for the composed function is in itself a documentation of what it does because it very clearly shows the steps:

let runImpeachmentProcess =
    investigateInHouse
    >=> voteInHouse
    >=> tryInSenate

I am in no way the inventor of this method. I just applied it to a world (in)famous ongoing process. Please have a look at the following sources:

Using single case union types for entity IDs in F# and make it work with Dapper

In C# it is a common and popular pattern to use strongly typed entity IDs instead of using integers or the likes for IDs on your entities. Strongly typed entity IDs is a great help when trying to prevent you from mixing an Order ID with an OrderLine ID.

Andrew Lock recently wrote a series on the topic that you should go read now.

A strongly typed entity ID may look something like this (the example used by Andrew Lock):

public readonly struct OrderId : IComparable<OrderId>, IEquatable<OrderId>
{
    public int Value { get; }

    public OrderId(int value)
    {
        Value = value;
    }

    public bool Equals(OrderId other) => this.Value.Equals(other.Value);
    public int CompareTo(OrderId other) => Value.CompareTo(other.Value);

    public override bool Equals(object obj)
    {
        if (ReferenceEquals(null, obj)) return false;
        return obj is OrderId other && Equals(other);
    }

    public override int GetHashCode() => Value.GetHashCode();
    public override string ToString() => Value.ToString();

    public static bool operator ==(OrderId a, OrderId b) => a.CompareTo(b) == 0;
    public static bool operator !=(OrderId a, OrderId b) => !(a == b);
}

That is a lot of code to write for every ID in your domain model and you should create a code snippet in Visual Studio to do it. However, as with many things you get this more or less for free in F# with single case union types. All it takes is this:

type CarID = CarID of int

F# will give to equal operators and the other stuff for free, hence:

let id1 = (CarID 42)
let id2 = (CarID 42)

id1 = id2 // true

As Scott Wlaschin points out on the legendary F# for fun and profit you can use single case union types for anything, not just IDs:

module Domain =
    type CarID = CarID of int
    type CarMake = CarMake of string
    type Model = Model of string

    type Car = {
        CarID: CarID;
        Make: CarMake;
        Year: int;
        Model: Model;
    }

I am not saying this is always a good idea but don’t take it for any more than an example.

What happens if you try to read a Car from a database with Dapper?

Single case union types and Dapper

Dapper uses reflection to create instances of your entity types either by calling the appropriate constructor or by setting properties. For F# record types you cannot set the properties so Dapper tries to call the constructor when querying the database:

use cn = getConnection ()
let cars = cn.Query<Car>("SELECT CarID, Make, Year, Model FROM Car")

This will fail because Dapper tries to find a constructor on OrderLine with the signature (int * string * int * string).

To help Dapper convert from int to CarID, from string to Make and so on you can register a type handler with Dapper. A type handler is a class that inherits SqlMapper.TypeHandler<>. For reading CarID from the database the type handler would look like this.

    type CarIDTypeHandler() =
        inherit SqlMapper.TypeHandler<CarID>()

        override x.SetValue(parameter: IDbDataParameter, value: CarID) =
            ()
        
        override x.Parse(value: obj) = 
            (CarID (Convert.ToInt32(value)))

You register the type handler with Dapper with SqlMapper.AddTypeHandler(typeof<CarID>, new CarIDTypeHandler()). It gets boring very quickly to write type handlers for every single single case union type you come up with (sorry about that strange sentence) and fortunately there is a way to write a generic type handler for single case union types using reflection.

    type SingleCaseUnionTypeHandler<'T>() =
        inherit SqlMapper.TypeHandler<'T>()

        override x.SetValue(parameter: IDbDataParameter, value: 'T) =
            ()
    
        override x.Parse(value: obj) =
            let cases = FSharpType.GetUnionCases(typedefof<'T>)
            FSharpValue.MakeUnion(cases.[0], [| value |]) :?> 'T

The last line makes use of FSharpValue.MakeUnion to create a union. It assumes that the union type 'T has one and only one case when using cases.[0]. I have not found a way to restrict the generic type parameter to unions.

Now you can register the type handler for all single case union types:

SqlMapper.AddTypeHandler(typeof<CarID>, new SingleCaseUnionTypeHandler<CarID>())
SqlMapper.AddTypeHandler(typeof<CarMake>, new SingleCaseUnionTypeHandler<CarMake>())
SqlMapper.AddTypeHandler(typeof<Model>, new SingleCaseUnionTypeHandler<Model>())

Closing

Above we have seen how we can easily use single case union types for type safe handling of entity IDs and other values to prevent using them interchangeably. We have also created a generic Dapper type handler for single case union types.

The generic type handler is only suitable for cases where you do not need extra logic or validation for creating your single union value types and you should also be careful when it comes to performance issues with the reflection in case you need to handle large amounts of instances.

Which is better for teaching? C# or F#

Recently I have had the pleasure of training a couple of colleagues in the wonders of programming. At work we use C# for most of our applications so naturally I started preparing my material in C#.

I did not get very far before it occurred to me: This is going to be a long haul…

Now, my colleagues are smart, really smart, much smarter than me, but they do not have much experience in programming. They have been using SQL, some VBA, and perhaps a bit of R, but none of them have been doing real application development and they know nothing about OO theory.

Unfortunately, you do not get very far with a language such as C# without knowing just a little bit about OO programming.

Let’s start with the compulsory and useless “Hello, world” example:

using System;

namespace ConsoleApp
{
class Program
{
static void Main(string[] args)
{
Console.WriteLine("Hello, world");
}
}
}

That’s a lot of code just to print out a stupid message on the screen.

“What are all those things for?” my colleague complains and I answer “We’ll get to namespaces, classes, static, void, arrays, and more stuff later”. He’s not happy and continues “Do I really need to write all those curly braces and semicolons?”. And when I tell him yes, and don’t forget that it’s all case sensitive, he breaks down and says “I miss VBA…”.

Of course curly brackets and case sensitivity has nothing to do with OO but I think we can all agree that OO is really, really hard. Heck, I don’t even master it after years of C++ and C#.

I find that it takes a long time for beginners to grasp OO and when they start to see the light they will abuse inheritance and create everything as singletons. And interfaces seem to be impossible to understand even though I do my best with lousy metafors such as cars and DVD playsers.

Usually, beginners actually tend to completely ignore that C# is object oriented and they take a straight forward approach and create a very long Main function.

So, perhaps teaching my colleagues C# is not the right approach. Perhaps I should try teaching them a functional language instead such as F#? Now, I am not saying that functional languages are easy but I do think that you can get really far with F# without knowing advanced stuff such as monads. In F# the “Hello, world” example boils down to

printfn "Hello, world"

Very simple. Not much to talk about.

Besides, there are a couple of important points to consider when bringing F# to the table:

  • My colleagues are all mathematicians and functional languages are perfect for math stuff.
  • F# is a .NET language and will work together with all the C# code in our company.
  • F# can work as a scripting language for makeshift assignments.

I am thinking that it would suffice to teach the basics of F# such as record types, functions, pattern matching, the Seq module, type providers, and perhaps partial application.

What do you think? Would F# be easier to grasp or should I go for the usual C#?