Rebind do notation with typeclass-free monad
<p>It is possible to rebind the (>>=) and return for a monad using explicit dictionary passing like this:</p>

<pre><code>{-# LANGUAGE RankNTypes #-}
{-# LANGUAGE RebindableSyntax #-}

module Lib where

import Prelude hiding ((&gt;&gt;=), return)

data MonadDict m = MonadDict {
  bind :: forall a b. m a -&gt; (a -&gt; m b) -&gt; m b ,
  ret :: forall a. a -&gt; m a }

(&gt;&gt;=) :: (MonadDict m -&gt; m a) -&gt; (a -&gt; (MonadDict m -&gt; m b)) -&gt; (MonadDict m -&gt; m b)
return :: a -&gt; (MonadDict m -&gt; m a)

monadDictIO :: MonadDict IO

usage = let
  monadicCode = do
    ln &lt;- const getLine 
    const . putStrLn $ ln
  in monadicCode monadDictIO
</code></pre>

<p>Is there a better way, how to represent the monad so one can avoid ignoring the <code>MonadDict</code> monad instance argument (using <code>const</code>) in every usage of the monadic action?</p>