Я в основном уверен, что то, что вы описываете, невозможно для ввода-вывода, который всегда является самой внутренней монадой:
От Мартина Грабмюллера: «Монадные трансформаторы шаг за шагом», доступно
http://www.grabmueller.de/martin/www/pub/
В этом документе мы вызываем liftIO в eval6 для выполнения действий ввода-вывода.
Зачем нам поднимать в этом случае? Потому что нет класса IO для
который мы можем создать экземпляр типа. Поэтому для действий ввода / вывода мы
нужно вызвать лифт, чтобы отправить команды внутрь
В целом, для монад, менее ограничивающих, чем IO, (например, Error и State) порядок все еще имеет значение для семантики, поэтому вы не можете изменить порядок стека, просто чтобы сделать синтаксис более удобным.
Для некоторых монад, таких как Reader, которые являются центральными (в том смысле, что они коммутируют в стеке), ваша идея кажется явно неосуществимой. Я не знаю, как написать это все же. Я предполагаю, что это будет класс типов CentralMonad
, экземпляром которого является ReaderT
, с некоторой реализацией ...