Относится к Экземпляр MonadTransControl для пользовательской монады , где, к сожалению (но вполне понятно), автор отказался от monad-control
.Однако, это не вариант для меня, потому что мне нужно использовать Control.Concurrent.Async.Lifted
в моей собственной монаде:
{-# LANGUAGE DataKinds, GADTs, ScopedTypeVariables #-}
data FeatureFlag = Feature1 | Feature2
newtype AppM (features :: [FeatureFlag]) a = AppM (ReaderT Env IO a)
deriving (Functor, Applicative, Monad, MonadReader Env, MonadIO, MonadThrow, MonadCatch, MonadMask, MonadUnliftIO)
Я пытался прочитать https://www.stackage.org/haddock/lts-12.1/monad-control-1.0.2.3/Control-Monad-Trans-Control.html, но, похоже, ничего не имеет смысламне. Концептуально Я понимаю, почему необходимы MonadBaseControl
и друзья, благодаря пошаговой инструкции на https://www.yesodweb.com/book/monad-control, но я не могу понять, как реализовать это.
Официальные документы имеют руководство по реализации в самом верху, но оно предполагает монадные преобразователи:
Определите экземпляры MonadTransControl T для всех преобразователей T, используя функции defaultLiftWith и defaultRestoreT дляконструктор и деконструктор T.
[...]
Определение экземпляров MonadBaseControl B m => MonadBaseControl B (T m) для всех преобразователей:
Как написать разумный экземпляр для MonadBaseControl IO (AppM fs)
, где часть fs
сохраняется, когда монада развернута и снова обернута? Кроме того, я предполагаю, что мне не нужно реализовывать MonadTransControl
, поскольку AppM fs
не является преобразователем.
PS: также связано - Безопасно ли получать MonadThrow, MonadCatch, MonadBaseControl, MonadUnliftIO и т. Д.?