Today I was enjoing the puzzle of figuring out which existing Haskell functions I could compose to make a specific new function. I suddenly realized that function design in a strongly typed language has a lot in common with dimensional analysis from physics.

Dimensional analysis is really useful for solving problems where you don’t have a direct conversion between units available. For a very simple example, suppose I walk 10000 steps per day and want to know how far I walk in a year. I don’t know the conversion from steps per day to km per year, but I can build one like so:

10000 steps/day * 0.7m/step * 365 days/year * 1km/1000m = 2555km/year

Similarly, you can often solve functional programming problems by composing
simple functions in the same way that these small units are composed into a
bigger conversion. Today I had a list of `Int`

and a function that produced
`Maybe Int`

. I wanted to find out if the value returned from the function was
in the list. You can do something like this:

```
f x `elem` [Just 1, Just 2, Just 3]
```

It seemed inelegant to have to keep repeating `Just`

for each value. Something
like this gets you a little closer, but it still feels like I’m typing out the
implementation details instead of writing the computation I want:

```
f x `elem` (map Just [1, 2, 3])
```

So then I backed up and asked how can I break down my original problem? I need
a function that combines a `Maybe a`

with `[a]`

and returns `Bool`

. Let me
look in the Maybe monad documentation for a function that looks like that.
Aha, `maybe`

is pretty close. It looks like

```
maybe :: b -> (a -> b) -> Maybe a -> b
```

It has that extra `b`

in there to represent the default value when `Nothing`

is
enountered, but that’s the price of generality. And then for the `a -> b`

function, we can go from `Int`

to `Bool`

based on whether the argument is in
the list. That function is called `(`elem` [1, 2, 3])`

. Putting this all
together, we can write:

```
maybeInList = maybe False (`elem` [1, 2, 3]) (f x)
```

If we want to check `Maybe`

values from different sources, we can leave off the
`(f x)`

part or pass it in as a parameter. Beautiful! This is at least as
clear as the original version, and it leaves the compiler and library
implementor free to do fancy optimizations later.

Of course, this is all just the basic rules of function composition, but I still thought it was fun to notice the similarity to dimensional analysis. It just goes to show that the same underlying mathematical mechanisms show up everywhere.