Я углубляюсь в монады Есода, и столкнулся с MonadBaseControl
.
Я взглянул на документ о взломе и потерялся. Может ли кто-нибудь сказать мне проблему, которую он пытается решить?
Для чего нужен MonadBaseControl?
Ответ 1
Он поставляется из пакета monad-control и является одним из двух классов типов (другой MonadTransControl), которые улучшают MonadBase (соответственно MonadTrans), поддерживая альтернативу liftBase
(соответственно lift
) для монодаров, которые ее реализуют. Эта расширенная версия больше не принимает простых действий в абсолютной базовой монаде (соответственно немедленной базовой монаде), но вместо этого принимает функцию, которая получает полное состояние базовой монады (соответственно монада-трансформатора) в этой точке в качестве единственного параметра и возвращает вышеупомянутое действие.
Как указывается в документации к пакету, это усовершенствование, наряду с остальной частью содержимого этих классов типов, позволяет вам снимать функции, такие как catch
, alloca
и forkIO
из абсолютной базовой монады (соответственно. немедленная базовая монада), что невозможно в более простой схеме, представленной в MonadBase (соответственно MonadTrans), потому что последняя пара не позволяет вам поднять аргументы функции, просто результаты, в то время как подход, используемый monad-control, позволяет обоим.
В результате набор монадов (соответственно монад-трансформаторов), которые можно использовать с MonadBaseControl (соответственно MonadTransControl) является строгим подмножеством множества монад, которые можно использовать с MonadBase (соответственно MonadTrans), но первые группы намного сильнее, чем последние по той же причине.
Ответ 2
Майкл Сноян на самом деле написал небольшой учебник по монад-контролю: http://www.yesodweb.com/book/monad-control
Суть этой статьи может быть следующей:
Представьте, что у вас есть этот фрагмент кода:
withMyFile :: (Handle -> IO a) -> IO a
withMyFile = withFile "test.txt" WriteMode
Вы можете применить withMyFile
к любой функции типа Handle -> IO a
и получить хорошее значение IO a
. Однако, что, если у вас есть функция типа Handle -> ErrorT MyError IO a
и вы хотите получить значение типа ErrorT MyError IO a
? Ну, в основном, вам придется изменить withMyFile
, чтобы включить много обертывания/разворачивания. MonadBaseControl позволяет несколько "поднять" функции, такие как withMyFile
, к определенным трансформаторам монады, которые позволяют разворачивать ( "работает" ). Таким образом, полученный код выглядит следующим образом:
useMyFileError :: (Handle -> ErrorT MyError IO ()) -> ErrorT MyError IO ()
useMyFileError func = control $ \run -> withMyFile $ run . func