program
has type
Elem (SimpleUniverse d) -> StateT (SimpleUniverse d) IO (Elem (SimpleUniverse d))
which indeed simplifies, but to
Elem d -> StateT (SimpleUniverse d) IO (Elem d)
and the inner withAgent
takes a program of type
Elem d -> StateT d IO (Elem d)
To fix that, this function will help:
stateMap :: Monad m => (s -> t) -> (t -> s) -> StateT s m a -> StateT t m a
stateMap f g (StateT h) = StateT $ liftM (fmap f) . h . g