## Motivation

I have some code which is presently run for its side effects, but I’d like it data too. It’s analogous to extending `writeFile`

to return the size of the contents:

```
writeFileAndCount :: FilePath -> String -> IO Int
writeFileAndCount path contents = do
writeFile path contents
return $ length contents
```

All well and good! Now we could just have two functions, one which returns `IO ()`

and the other which returns `IO Int`

, but it seems a shame to pollute the namespace. Instead it would be nice if we could say e.g.:

```
ghci> writeFile' "foo.txt" "Hello" :: IO ()
ghci> writeFile' "foo.txt" "Hello" :: IO Int
5
```

Happily we can!

## A mathematical analogy

You’ve probably already seen code whose return type changes to match the context. For example in Haskell’s maths libraries many functions will return either `Float`

or `Double`

. Here’s `sqrt`

:

```
ghci> (sqrt 2) :: Float
1.4142135
ghci> (sqrt 2) :: Double
1.4142135623730951
```

To see how this works, look at the type of `sqrt`

:

```
ghci> :t sqrt
sqrt :: Floating a => a -> a
```

There’s no mention of `Double`

or `Float`

there. Instead, we see that `sqrt`

will work with any instance of the `Floating`

typeclass.

Under the covers we’d expect different instances of `sqrt`

: one `Double -> Double`

, another `Float -> Float`

. Having inferred the relevant type, the compiler will then pick the particular instance we need.

Conceptually we might have:

```
sqrtD :: Double -> Double
sqrtF :: Float -> Float
sqrt :: (Floating a) => a -> a
```

Note that all of these functions don’t change the type: we can’t implicitly change e.g. a `Float`

to a `Double`

:

```
ghci> (sqrt (2 :: Float)) :: Double
<interactive>:5:8:
Couldn't match expected type ‘Double’ with actual type ‘Float’
In the first argument of ‘sqrt’, namely ‘(2 :: Float)’
In the expression: (sqrt (2 :: Float)) :: Double
In an equation for ‘it’: it = (sqrt (2 :: Float)) :: Double
```

This is because the signature has just one degree-of-freedom:

`sqrt :: a -> a`

rather than

`sqrt :: a -> b`

## A polymorphic wrapper

Having seen that `sqrt`

can choose different code in different contexts, let’s try to write a combinator which either passes a value unchanged, or converts it to `()`

.

By analogy with `sqrt`

consider combining:

```
toId :: a -> a
toUnit :: a -> ()
```

Although the first equation both accepts and returns the same type, the second doesn’t. So it makes sense to invent a type class with two parameters. On a technical level, this means we’ll need the `MultiParamTypeClasses`

^{1} GHC extension.

Here’s a suitable type class:

```
class OrUnit b a where
orUnit :: a -> b
```

We also need a couple of instances:

```
instance OrUnit () a where
orUnit a = ()
instance OrUnit a a where
orUnit a = a
```

In the first instance above, the `()`

is a concrete type rather than a variable, so we’ll also need the `FlexibleInstances`

^{2} extension.

Given this, we can write things like this:

```
ghci> orUnit 'a' :: Char
'a'
ghci> orUnit 'a' :: ()
()
```

or indeed our original goal of `writeFile'`

:

```
writeFile' :: (OrUnit a Int) => FilePath -> String -> IO a
writeFile' path contents = liftM orUnit
$ writeFileAndCount path contents
```

We need `liftM`

to lift `orUnit`

into the IO Monad.

## Problems

Although we’ve met our original goal of adding optional return data from a function whilst keeping compatibility with old code, it isn’t perfect.

We saw above that we need GHC extensions to compile the module. Sadly we also need to enable extensions when using it:

```
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE FlexibleContexts #-}
```

So, it’s doesn’t give a completely backwards-compatible way to extend the original API.

Also the extra flexibility we enjoy seems to force us to specify explicit types more often. Perhaps other GHC extensions would help here.

## The code

You can grab the code from GitHub^{3}. It’s just for fun, and consequently I’ve not uploaded it to hackage.

## References

- 1. https://wiki.haskell.org/Multi-parameter_type_class
- 2. http://connectionrequired.com/blog/2009/07/my-first-introduction-to-haskell-extensions-flexibleinstances/
- 3. https://github.com/mjoldfield/or-unit