abstract over MonadReader and MonadIO