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 (
, ZipperT
, runZipperT
) where

import Control.Applicative

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

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 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!

+3

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`

``````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
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
```

```
+3

source

All Articles