<html><head><meta http-equiv="Content-Type" content="text/html; charset=us-ascii"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;" class="">Greetings!<div class=""><br class=""></div><div class="">This is also posted at <a href="https://www.reddit.com/r/haskell/comments/o4sggi/is_monadbasecontrol_dead/" class="">https://www.reddit.com/r/haskell/comments/o4sggi/is_monadbasecontrol_dead/</a> but I'd like to also seek wider help here.</div><div class=""><br class=""></div><div class=""><div class="">(Background issue I'm facing: <a href="https://github.com/snapframework/snap-core/issues/309" class="">https://github.com/snapframework/snap-core/issues/309</a>)</div><div class=""><br class=""></div><div class="">I think the functionality of [MonadUnliftIO](<a href="https://hackage.haskell.org/package/unliftio-core-0.2.0.1/docs/Control-Monad-IO-Unlift.html#t:MonadUnliftIO" class="">https://hackage.haskell.org/package/unliftio-core-0.2.0.1/docs/Control-Monad-IO-Unlift.html#t:MonadUnliftIO</a>) is exactly what I want, but unfortunately [Snap](<a href="https://hackage.haskell.org/package/snap-core-1.0.4.2/docs/Snap-Core.html#t:Snap" class="">https://hackage.haskell.org/package/snap-core-1.0.4.2/docs/Snap-Core.html#t:Snap</a>) appears not eligible for:</div><div class=""><br class=""></div><div class="">> the intuition is that a monad must have no monadic state, but may have monadic context. This essentially limits MonadUnliftIO to ReaderT and IdentityT transformers on top of IO.</div><div class=""><br class=""></div><div class="">Then I found `Snap` [has a MonadBaseControl instance](<a href="https://hackage.haskell.org/package/snap-core-1.0.4.2/docs/src/Snap.Internal.Core.html#line-347" class="">https://hackage.haskell.org/package/snap-core-1.0.4.2/docs/src/Snap.Internal.Core.html#line-347</a>), and thought it should work for me. But sadly to find it [losing states](<a href="https://github.com/snapframework/snap-core/issues/309" class="">https://github.com/snapframework/snap-core/issues/309</a>). Also I failed to find a user side example of `MonadBaseControl` on Github ([as there're only instance impl. hits](<a href="https://github.com/search?l=Haskell&q=org%3Asnapframework+liftBaseWith&type=Code" class="">https://github.com/search?l=Haskell&q=org%3Asnapframework+liftBaseWith&type=Code</a>)), so I have not way to verify whether that's due to my incorrect usage.</div><div class=""><br class=""></div><div class="">Any way quoting u/snoyberg : <a href="https://github.com/fpco/unliftio/issues/17#issuecomment-363655106" class="">https://github.com/fpco/unliftio/issues/17#issuecomment-363655106</a></div><div class="">> Continuation-based monads cannot have instances of MonadUnliftIO, the same as MonadBaseControl and MonadMask. </div><div class=""><br class=""></div><div class="">Then I'm not sure `Snap`'s `MonadBaseControl` instance shall really work.</div><div class=""><br class=""></div><div class="">Also seems there had been debates I'm not aware of with clue at: <a href="https://github.com/fpco/unliftio/tree/master/unliftio#monad-control" class="">https://github.com/fpco/unliftio/tree/master/unliftio#monad-control</a></div><div class="">> </div><div class="">> The main contention until now is that unlifting in a transformer like</div><div class="">> `StateT` is unsafe. This is not universally true: if only one action</div><div class="">> is being unlifted, no ambiguity exists. So, for example, `try :: IO a</div><div class="">> -> IO (Either e a)` can safely be unlifted in `StateT`, while `finally</div><div class="">> :: IO a -> IO b -> IO a` cannot.</div><div class="">> </div><div class="">> `monad-control` allows us to unlift both styles. In theory, we could</div><div class="">> write a variant of `lifted-base` that never does state discards, and</div><div class="">> let `try` be more general than `finally`. In other words, this is an</div><div class="">> advantage of `monad-control` over `MonadUnliftIO`. We've avoided</div><div class="">> providing any such extra typeclass in this package though, for two</div><div class="">> reasons:</div><div class="">> </div><div class="">> * `MonadUnliftIO` is a simple typeclass, easy to explain. We don't</div><div class="">>   want to complicated matters (`MonadBaseControl` is a notoriously</div><div class="">>   difficult to understand typeclass). This simplicity</div><div class="">>   is captured by the laws for `MonadUnliftIO`, which make the</div><div class="">>   behavior of the run functions close to that of the already familiar</div><div class="">>   `lift` and `liftIO`.</div><div class="">> * Having this kind of split would be confusing in user code, when</div><div class="">>   suddenly `finally` is not available to us. We would rather encourage</div><div class="">>   [good practices](<a href="https://www.fpcomplete.com/blog/2017/06/readert-design-pattern" class="">https://www.fpcomplete.com/blog/2017/06/readert-design-pattern</a>)</div><div class="">>   from the beginning.</div><div class="">> </div><div class="">> Another distinction is that `monad-control` uses the `MonadBase`</div><div class="">> style, allowing unlifting to arbitrary base monads. In this package,</div><div class="">> we've elected to go with `MonadIO` style. This limits what we can do</div><div class="">> (e.g., no unlifting to `STM`), but we went this way because:</div><div class="">> </div><div class="">> * In practice, we've found that the vast majority of cases are dealing</div><div class="">>   with `IO`</div><div class="">> * The split in the ecosystem between constraints like `MonadBase IO`</div><div class="">>   and `MonadIO` leads to significant confusion, and `MonadIO` is by</div><div class="">>   far the more common constraints (with the typeclass existing in</div><div class="">>   `base`)</div><div class="">></div><div class=""><br class=""></div><div class="">So is `MonadBaseControl` dead or alive? Any user side example for it?</div></div><div class=""><br class=""></div></body></html>