## Rebind do notation with typeclass-free monad

Question

It is possible to rebind the (>>=) and return for a monad using explicit dictionary passing like this:

```
{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE RebindableSyntax #-}
module Lib where
import Prelude hiding ((>>=), return)
data MonadDict m = MonadDict {
bind :: forall a b. m a -> (a -> m b) -> m b ,
ret :: forall a. a -> m a }
(>>=) :: (MonadDict m -> m a) -> (a -> (MonadDict m -> m b)) -> (MonadDict m -> m b)
return :: a -> (MonadDict m -> m a)
monadDictIO :: MonadDict IO
usage = let
monadicCode = do
ln <- const getLine
const . putStrLn $ ln
in monadicCode monadDictIO
```

Is there a better way, how to represent the monad so one can avoid ignoring the `MonadDict`

monad instance argument (using `const`

) in every usage of the monadic action?

Show source

## Answers ( 2 )

You can do like this:

The short and incorrect answer is drop the

`MonadDict m`

argument from the return type of the second argument to`(>>=)`

:But that doesn't really solve all of your syntax problems. If someone has an existing arrow with the type

`Monad m => a -> m b`

, with explicit dictionary passing it'll have the type`a -> (MonadDict m -> m b)`

, and won't be usable as the second argument to`(>>=)`

. If there were a function`drop :: (MonadDict m -> m b) -> m b`

to make it compatible with the second argument then there'd be no reason to pass`MonadDict`

s around.You're reinventing the

`ReaderT`

transformer to read a`MonadDict m`

.Every time you're using

`const`

it's the equivalent of`lift`

ing an`m a`

into`ReaderT (MonadDict m) m a`

. Your example wouldn't look so unfamiliar if you wrote it with`lift`

instead of`const`

.Here's a complete example using

`ReaderT`

; it'd probably be better to make a new type for`ReaderT (MonadDict m) m`

and a different name for`lift`

. The implementation of`(>>=)`

and`return`

is identical to`ReaderT`

s, except it uses the`bind`

or`ret`

from the`MonadDict`

.If you give it its own type you can equip it with a

`Monad`

instance independently of the underlying`m`

, and dispense with`RebindableSyntax`

.