The usual way to define an indexed monad a la Atkey is:
class IxMonad m where
  ireturn :: a -> m i i a
  ibind   :: m i j a -> (a -> m j k b) -> m i k b
Another approach is found in the work of McBride (also discussed by him here):
type f :-> g = forall i. f i -> g i
class MonadIx (m :: (state -> *) -> (state -> *)) where
  returnIx    :: f :-> m f
  flipBindIx  :: (f :-> m g) -> (m f :-> m g)
The type of flipBindIx is isomorphic to bindIx :: forall i. m f i -> (forall j. f j -> m g j) -> m g i. Whereas normal Haskell monads characterize m :: * -> * (and the 'normal' indexed monads characterize m :: state -> state -> * -> *), MonadIx characterizes monads m :: (state -> *) -> state -> *. That's why I'm calling the latter 'higher-order' (but if there's a better name, let me know).
While this makes a certain amount of sense, and I can see certain structural similarities between the two encodings, I am having difficulty with a few things. Here are a few questions that seem related:
Most basically, I just don't understand how to use
MonadIxto write a simple indexed state monad -- the one that inIxMonadlooks just like the regular state monad, with more general types.Relatedly, in the previously linked SO question, Kmett discusses a way to 'recover the power of'
IxMonadfromMonadIx. The technique isn't completely demonstrated, however (and I can't get the associated code to compile, anymore).MonadIxis stronger thanIxMonad. This suggests that there should be a mapping from anyIxMonad m => m i o ato someMonadIx m => m f(or is ism f i?), but not the reverse, right? What is that mapping?Finally, parametricity abounds in the definition of
MonadIx. ButIxMonadactions can freely make demands about the shape of the incoming state, as inm :: IxMonad m (a, i) i a. How do these sorts of actions look inMonadIx?