Impeachment in a functional way
Tags: functional, fsharp
Published: 2020-01-13 15:38:08

---
title: Impeachment in a functional way
published: true
date: 2020-01-13 15:23:32 UTC
tags: functional programming,FSharp
cover_image: https://i1.wp.com/leruplund.dk/wp-content/uploads/2020/01/DSC_0538-Edit-small.jpg?w=1670
canonical_url: http://leruplund.dk/2020/01/13/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](https://www.axios.com/the-process-of-impeachment-d4af789d-7166-4101-a1c8-dba6ffb8b420.html) 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:

```csharp
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.

```csharp
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#):

```fsharp
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:

```fsharp
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`:

```fsharp
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:

```fsharp
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 `exitAt`parameter 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:

```fsharp
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:

```fsharp
let runImpeachmentProcess =
    investigateInHouse
    >=> voteInHouse
    >=> tryInSenate
```

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

```fsharp
runImpeachmentProcess:ExitAtStep -> ImpeachmentResult<ExitAtStep>
```

Let’s run it:

```fsharp
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:

```fsharp
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:

```fsharp
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:

- [F# for fun and profit: Railway oriented programming.](https://fsharpforfunandprofit.com/posts/recipe-part2/)
- [F# for fun and profit: Against railway oriented programming](https://fsharpforfunandprofit.com/posts/against-railway-oriented-programming/).
- [Category theory for programmers.](https://github.com/hmemcpy/milewski-ctfp-pdf)