# Magical Monoids

Recently something caught my eye while hacking on a Haskell

project. Pay attention to the `mempty`

in the code fragment below:

readTextFileUtf8 :: FilePath -> IO (Either Utf8Error T.Text)

readTextFileUtf8 filename = {- ... -}-- | Return "" in case of errors

lenientReadTextFileUtf8 :: FilePath -> IO T.Text

lenientReadTextFileUtf8 filename = do

result <- readTextFileUtf8 filename

pure $ either (\_ -> mempty) id result

I went about my favourite pastime did some code-golfing on `lenientReadTextFileUtf8`

but inadvertently made a mistake while refactoring which didn’t result in a type error:

`lenientReadTextFileUtf8' :: FilePath -> IO T.Text`

lenientReadTextFileUtf8' filename

= either mempty pure =<< readTextFileUtf8 filename

Can you spot the “mistake”?

I should have written

`... = either (\_ -> pure mempty) pure =<< ...`

as in my mind I expected `mempty`

to be `(“” :: Text)`

and to my surprise the code actually even worked in the way I wanted it to!

So it was time to go deeper and investigate. After reading up on the `base`

documentation I quickly found out that there’s two peculiar instances*(1)* defined for `Monoid`

which enable this type magic:

instance Monoid b => Monoid (a -> b) where

mempty = \_ -> memptyinstance Monoid a => Monoid (IO a) where

mempty = pure mempty

In other words, `mempty`

can be specialised into an infinite number of functions according to the repeated application of the definitions above:

`mempty :: IO Text`

mempty :: IO (IO (IO Text))

mempty :: IO (a -> IO (b -> Text))

mempty :: a -> Text

mempty :: a -> b -> Text

mempty :: a -> b -> IO Text

mempty :: a -> b -> IO (IO Text)

So whenever you’re too lazy to write nested forms of `const`

or `pure`

you can just let the Haskell compiler magically generate those forms on the fly for you via the magic of type inference!

But there’s more! Check out the associated `Semigroup`

instances

`instance Semigroup b => Semigroup (a -> b) where`

f <> g = \x -> f x <> g x

instance Semigroup a => Semigroup (IO a) where

(<>) = liftA2 (<>)

With those you can now write stuff like

`>>> (take 3 <> const "oi" <> drop 4) "Monads are cool!"`

"Monoids are cool!"

or

`readTextFileUtf8OrLatin1 :: FilePath -> IO (Either String T.Text)`

readTextFileUtf8OrLatin1 = readTextFileUtf8 <> readTextFileLatin1

which tries to read a file in UTF8 format and if that fails falls back to reading as Latin1. Aren’t `Monoid`

s super awesome? Do you know of other cool `Monoid`

magical tricks?

## Footnotes:

*(1)* Wouldn’t it be even cooler if this worked for every `Applicative`

?

instance (Applicative f, Semigroup a) => Semigroup (f a) where

(<>) = liftA2 (<>)instance (Applicative f, Monoid a) => Monoid (f a) where

mempty = pure mempty

**Update**: On Reddit phadej and others pointed out there’s the `Ap`

newtype wrapper defined in the latest `base`

release which allows just that! Its definition is

newtype Ap f a = Ap { getAp :: f a }instance (Applicative f, Semigroup a) => Semigroup (Ap f a) where

(Ap x) <> (Ap y) = Ap $ liftA2 (<>) x yinstance (Applicative f, Monoid a) => Monoid (Ap f a) where

mempty = Ap $ pure mempty