Today let us visit a lesser known data type: `These`

. I came across it first while working at Formation. I can't remember the first use of it, but I do remember how I ended up using it a while later, and a colleague using it in the exact same way; vindication, yes! So what we'll cover in this post is what the `These`

data type is, how it can be used, and how we used it to manage feature flags & safe code migrations.

## This, That, and the Other

`These`

can be thought of as `Either`

, but extend it with an extra case where one variant can hold both values. Code speaks louder than words so here's what it would look like in Haskell:

Earlier we said that `These`

can be thought of as an extended `Either`

, so let's examine the similarities. With `Either`

we have the `Left`

case which holds a value of type `a`

and `Right`

which holds a value of type `b`

.

With `These`

we have a `This`

case which holds a value of type `a`

(similar to `Left`

) and a `That`

case which holds a value of type `b`

(similar to `Right`

). We extend our two cases with one more case, `These`

, which holds two values, one of type `a`

and one of type `b`

. Another way to think about this is that we're removing the mutual exclusivity that we see using `Either`

by allowing both values to occur at once as well.

## Those Useful Functions

What kind of things can we do with `These`

? What's in our toolbox with this new data type? We have our usual suspects, `These`

is a `Functor`

so we can use `fmap`

on it:

```
instance Functor (These a) where
fmap f (This a) = This a
fmap f (That b) = That (f b)
fmap f (These a b) = These a (f b)
```

We also have `Applicative`

and `Monad`

instances as long as the `a`

is a `Semigroup`

:

```
instance Semigroup a => Applicative (These a) where
pure = That
This a <*> _ = This a
That _ <*> This b = This b
That f <*> That x = That (f x)
That f <*> These b x = These b (f x)
These a _ <*> This b = This (a <> b)
These a f <*> That x = These a (f x)
These a f <*> These b x = These (a <> b) (f x)
instance Semigroup a => Monad (These a) where
return = pure
This a >>= _ = This a
That x >>= f = f x
These a x >>= f = case f x of
This b = This (a <> b)
That y = These a y
These b y = These (a <> b) y
```

What we can glean from this behaviour is that it is short-circuiting when encountering `This`

unless we also encounter a `These`

, then we want to gather `a`

s while also preserving the `b`

value.

The final useful instance (in my humble opinion) in the `These`

toolbox is its `Bifunctor`

instance:

```
instance Bifunctor These where
bimap f _ (This a) = This (f a)
bimap _ g (That b) = That (g b)
bimap f g (These a b) = These (f a) (g b)
```

This allows to apply functions to transform any of the values inside. We can target the `a`

s, the `b`

s, or both.

## Migrating Them

Now that we know how to use `These`

, let's talk about one use case for the data type. When I was working on a couple of features in Formation I was adding functionality to an existing code path. A healthy dose of paranoia meant that we wanted make these changes so that we could deploy things in a phased fashion. We would create an enumeration that would look like the following:

```
data FeatureMigration
= NoChange -- ^ Don't use the new code path at all
| SafeChange -- ^ Use the new code path and fall back on the old path
| FullChange -- ^ Use the new code path only
```

Let's take an example of what one of these migrations would involve. In one case we were validating data. Initially this was a simple look up of a `Map`

and placing the values into a domain type. Roughly speaking, we would have a function `validate`

like:

Later we wanted to supercharge this validation by inspecting the values and checking invariants on them. For example, if we were dealing with numbers we would check that they were greater than zero. The aforementioned paranoia set in and we wanted to ensure that any data that was already persisted could still be validated. We already had persisted data that got past the previous validation function but we cannot be sure that it would pass the new validation.

Imagine the following scenario. We add a check in our validation saying that we do not want to process lists that are longer than 5. Unbeknownst to us we have persisted a list that is of length 6. This data is in production and is technically still valid. In the future this would prevented by our validation logic, but for now it lives on. So essentially we want to have backwards compatibility while we monitor things that go wrong.

So where does `These`

come into this? Well we conveniently have a three-way case of calling code! We want to make sure that any errors that can happen in any of the code paths are handled and placed in the `This`

case. If we are successful in validating without any errors we return our errors in `That`

. The interesting case is where we want to fall back on the old validation when the new validation fails. If the new code path fails but the old code path succeeds we will return the result in `These`

. Let's look at some pseudo-code to drive this point home.

```
import qualified Validation.Old as Old
import qualified Validation.New as New
data ValidationErrors
= OldValidationErrors Old.ValidationErrors
| NewValidationErrors New.ValidationErrors
validate :: FeatureMigration -> Map Key Value -> These ValidationErrors DomainType
validate migration kvs =
let oldValidation = Old.validate kvs
newValidation = New.validate kvs
in case migrations of
NoChange -> either (This . OldValidationErrors) That oldValidation
FullChange -> either (This . NewValidationErrors) That newValidation
SafeChange ->
either
-- New validation failed so delegate to old validation
(\errs -> either (This . OldValidationErrors) (These errs) oldValidation)
-- New validation succeeded so we're safe
That
newValidation
```

From there we can call `validate`

and if we want to keep track of any deviations in the `SafeChange`

case, we can log messages and/or metrics:

```
case validate kvs of
These errs result -> do
logValidationErrors errs
updateValidationErrorMetricCount errs
processResult result
This errs -> do
logValidationErrors errs
err500
That result ->
processResult result
```

## Conclusion

So next time you're considering adding some new functionality you want to carefully monitor, consider using the `these`

package and the technique above. For posterity's we will also link the `monad-chronicle`

package which is the Monad Transformer for `These`

. And for some self-promotion, if you're also in the Rust world I ported some of this functionality in my `these`

crate.