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
MonadIx
to write a simple indexed state monad -- the one that inIxMonad
looks 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'
IxMonad
fromMonadIx
. The technique isn't completely demonstrated, however (and I can't get the associated code to compile, anymore).MonadIx
is stronger thanIxMonad
. This suggests that there should be a mapping from anyIxMonad m => m i o a
to 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
. ButIxMonad
actions 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
?