This is a literate Haskell post. You can play with the examples in ghci, in a stack playground, calling:

`stack ghci --package transformers --package transformers-base --package monad-control --package distributed-process --package distributed-process-monad-control`

Let’s start with some imports:

```
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE MultiParamTypeClasses #-}
{-# LANGUAGE TypeSynonymInstances #-}
{-# LANGUAGE FlexibleInstances #-}
{-# LANGUAGE TypeFamilies #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
import Control.Monad.Base
import Control.Monad.State hiding (StateT, runStateT, execStateT, evalStateT, get)
import Control.Monad.Trans.Control
import Control.Monad.Trans.State.Strict
import Control.Distributed.Process
import Control.Distributed.Process.MonadBaseControl
```

Consider this monad:

```
data Ctx = Ctx () -- some kind of env, not important.
newtype RemotePure m a = RemotePure { runRemote :: StateT Ctx m a }
deriving (Functor, Applicative, Monad, MonadState Ctx, MonadIO)
type RemoteM = RemotePure Process
instance MonadBase IO (RemotePure Process) where
= RemotePure . liftBase liftBase
```

You now would like to write an instance for MonadBaseControl.

This is the definition of `MonadBaseControl`

and `RunInBase`

(at the time of writing, April 2017):

```
class MonadBase b m => MonadBaseControl b m | m -> b where
type StM m a :: *
liftBaseWith :: (RunInBase m b -> b a) -> m a
restoreM :: StM m a -> m a
type RunInBase m b = forall a. m a -> b (StM m a)
```

A legitimate question is: how can I write the correct right hand side for `StM`

? As you might know, when the `type`

keyword is being used in a type class definition we are not dealing with a *type synonym* but with a *type family*. A *type family* is essentially a function with operates on *types*, not *values*, like “normal” functions. But how can I pick the correct RHS? How would I know? There are two approaches: one seems to be the most popular, but it requires the use of `UndecidableInstances`

, the other was found in this small nugget of wisdom^{1} over at Stack Overflow.

The first one is this:

```
instance MonadBaseControl IO RemoteM where
type StM RemoteM a = StM (StateT Ctx Process) a
= RemotePure $ liftBaseWith $ \q -> f (q . runRemote)
liftBaseWith f = RemotePure . restoreM restoreM
```

Why this works? Also, it might not be immediately clear why `StM`

appears on the right hand side. You might ask yourself “Did he just pull out the type StM out of thin air and reused it?”. It’s allright, I have been there myself. Haskell notation is so dense sometimes it’s easy to get lost. The key insigth is this: **StM is NOT a type, is a type-level FUNCTION!** Here, all we are doing is calling `StM`

on the RHS, effectively offloading computing the result and hoping that somebody already defined in the stack the final solution. So we are effectively applying `StM`

to `(StateT Ctx Process) a`

as an argument. And this is exactly *why* GHC asks us to enable `UndecidableInstances`

. It cannot guarantee, without compiling the program, that GHC will terminate. Effectively (if I recall correctly what Andres Loh once told us in an Haskell course in London), as scary as the name might sound, `UndecidableInstances`

simply tells us “hey, it’s probably going to be fine, but there is a chance the typechecking might not terminate”. This is (very loosely speaking) because the RHS doesn’t “reduce” as it has the same number of terms of the LHS, so GHC gets suspicious.

The other approach is to simply ask GHC for the result of the type family. How? Let’s fire up `ghci`

, and let’s type this:

```
ghci> :set -XRankNTypes
ghci> import Control.Monad.Trans.Control
ghci> :kind! forall a. StM RemoteM a
forall a. StM RemoteM a :: *
= (a, Ctx)
```

Wow, can you believe how easy it was? It’s equally easy to convince ourselves why this result makes sense: this is nothing more of the result of applying `Stm`

to `StateT Ctx Process`

. Let’s find out:

```
ghci> import Control.Monad.Trans.State.Strict
ghci> import Control.Distributed.Process
ghci> :kind! forall a. StM (StateT Ctx Process) a
forall a. StM (StateT Ctx Process) a :: *
= (a, Ctx)
```

And the best part is that now we don’t need `UndecidableInstances`

, and we are much more confident we are computing `StM`

the right way. Our definition becomes:

```
instance MonadBaseControl IO RemoteM where
type StM RemoteM a = (a, Ctx)
= RemotePure $ liftBaseWith $ \q -> f (q . runRemote)
liftBaseWith f = RemotePure . restoreM restoreM
```

Thanks, Daniel Wagner!↩︎

Loved this post? Stay update!