# Build my own monad transformer module hiding the main monad

I am learning mtl and I want to know the correct way to create new monads as modules (not as a typical application use).

As a simple example, I wrote `ZipperT`

monad here ( full code ):

```
{-# LANGUAGE FlexibleInstances, FunctionalDependencies, MultiParamTypeClasses, GeneralizedNewtypeDeriving #-}
module ZipperT (
MonadZipper (..)
, ZipperT
, runZipperT
) where
import Control.Applicative
import Control.Monad.State
class Monad m => MonadZipper a m | m -> a where
pushL :: a -> m ()
pushR :: a -> m ()
...
data ZipperState s = ZipperState { left :: [s], right :: [s] }
newtype ZipperT s m a = ZipperT_ { runZipperT_ :: StateT (ZipperState s) m a }
deriving ( Functor, Applicative
, Monad, MonadIO, MonadTrans
, MonadState (ZipperState s))
instance (Monad m) => MonadZipper s (ZipperT s m) where
pushL x = modify $ \(ZipperState left right) -> ZipperState (x:left) right
pushR x = modify $ \(ZipperState left right) -> ZipperState left (x:right)
...
runZipperT :: (Monad m) => ZipperT s m a -> ([s], [s]) -> m (a, ([s], [s]))
runZipperT computation (left, right) = do
(x, ZipperState left' right') <- runStateT (runZipperT_ computation) (ZipperState left right)
return (x, (left', right'))
```

it works and i can compose with other monads

```
import Control.Monad.Identity
import Control.Monad.State
import ZipperT
length' :: [a] -> Int
length' xs = runIdentity (execStateT (runZipperT contar ([], xs)) 0)
where contar = headR >>= \x -> case x of
Nothing -> return ()
Just _ -> do
right2left
(lift . modify) (+1)
-- ^^^^^^^
contar
```

But I want to avoid being explicit `lift`

.

- What is the correct way to create such modules?
- Can you avoid the explicit
`lift`

? (I want to hide the inner structure of`StateT`

mine`ZipperT`

)

Thank!

source to share

I think if you can write an instance `MonadState`

for your transformer, you can use `modify`

without `lift`

:

```
instance Monad m => MonadState (ZipperT s m a) where
...
```

I have to admit, I'm not sure which part of the condition `modify`

should be affected, though.

I have looked at the complete code. It seems that you have already identified

```
MonadState (ZipperState s) (ZipperT s m)
```

This already provides `modify`

, which, however, changes the wrong baseline. What you really wanted was to expose the state wrapped in `m`

, provided that it is `MonadState`

. In theory, this could be done with

```
instance MonadState s m => MonadState s (ZipperT s m) where
...
```

But now we have two instances `MonadState`

for the same monad, resulting in a conflict.

I guess I solved it somehow.

Here's what I did:

First, I deleted the original instance `deriving MonadState`

. Instead, I wrote

`getZ :: Monad m => ZipperT s m (ZipperState s) getZ = ZipperT_ get putZ :: Monad m => ZipperState s -> ZipperT s m () putZ = ZipperT_ . put modifyZ :: Monad m => (ZipperState s -> ZipperState s) -> ZipperT s m () modifyZ = ZipperT_ . modify`

and replaced the previous entries `get,put,modify`

in the library `ZipperT`

with the above UDFs.

Then I added a new instance:

```
-- This requires UndecidableInstances
instance MonadState s m => MonadState s (ZipperT a m) where
get = lift get
put = lift . put
```

And now the client code works without elevators:

```
length' :: [a] -> Int
length' xs = runIdentity (execStateT (runZipperT contar ([], xs)) 0)
where contar :: ZipperT a (StateT Int Identity) ()
contar = headR >>= \x -> case x of
Nothing -> return ()
Just _ -> do
right2left
modify (+ (1::Int))
-- ^^^^^^^
contar
```

source to share