Ответ 1
Рассмотрим конкретный пример IOT Maybe
. Как вы могли бы написать экземпляр Monad
для этого? Вы можете начать с чего-то вроде этого:
instance Monad (IOT Maybe) where
return x = IOT (Just (return x))
IOT Nothing >>= _ = IOT Nothing
IOT (Just m) >>= k = IOT $ error "what now?"
where m' = liftM (runIOT . k) m
Теперь у вас есть m' :: IO (Maybe (IO b))
, но вам нужно что-то типа Maybe (IO b)
, где - самое главное - выбор между Just
и Nothing
должен определяться m'
. Как это будет реализовано?
Ответ, конечно, заключается в том, что это не так, потому что это невозможно. Вы также не можете обосновать unsafePerformIO
там, скрытый за чистым интерфейсом, потому что в основном вы запрашиваете чистое значение - выбор конструктора Maybe
- зависеть от результата чего-то в IO
. Nnnnnope, не произойдет.
В общем случае ситуация еще хуже, потому что произвольное (универсально квантифицированное) Monad
еще более невозможно развернуть, чем IO
.
Кстати, используемый вами трансформатор ST
реализован иначе, чем предлагаемый IOT
. Он использует внутреннюю реализацию ST
в качестве State
-подобной монады с использованием специальных примитивов magic pixie dust, предоставляемых компилятором, и на основе этого определяет трансформатор StateT
. IO
реализуется внутри как еще более магический ST
, и поэтому гипотетический IOT
может быть определен аналогичным образом.
Не то, чтобы это действительно меняло что-то, отличное от того, что, возможно, давало вам лучший контроль над относительным упорядочением нечистых побочных эффектов, вызванных IOT
.