[Haskell-cafe] Is `MonadBaseControl` dead?

YueCompl compl.yue at icloud.com
Mon Jun 21 11:44:27 UTC 2021


This is also posted at https://www.reddit.com/r/haskell/comments/o4sggi/is_monadbasecontrol_dead/ <https://www.reddit.com/r/haskell/comments/o4sggi/is_monadbasecontrol_dead/> but I'd like to also seek wider help here.

(Background issue I'm facing: https://github.com/snapframework/snap-core/issues/309)

I think the functionality of [MonadUnliftIO](https://hackage.haskell.org/package/unliftio-core- is exactly what I want, but unfortunately [Snap](https://hackage.haskell.org/package/snap-core- appears not eligible for:

> 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.

Then I found `Snap` [has a MonadBaseControl instance](https://hackage.haskell.org/package/snap-core-, and thought it should work for me. But sadly to find it [losing states](https://github.com/snapframework/snap-core/issues/309). Also I failed to find a user side example of `MonadBaseControl` on Github ([as there're only instance impl. hits](https://github.com/search?l=Haskell&q=org%3Asnapframework+liftBaseWith&type=Code)), so I have not way to verify whether that's due to my incorrect usage.

Any way quoting u/snoyberg : https://github.com/fpco/unliftio/issues/17#issuecomment-363655106
> Continuation-based monads cannot have instances of MonadUnliftIO, the same as MonadBaseControl and MonadMask. 

Then I'm not sure `Snap`'s `MonadBaseControl` instance shall really work.

Also seems there had been debates I'm not aware of with clue at: https://github.com/fpco/unliftio/tree/master/unliftio#monad-control
> The main contention until now is that unlifting in a transformer like
> `StateT` is unsafe. This is not universally true: if only one action
> is being unlifted, no ambiguity exists. So, for example, `try :: IO a
> -> IO (Either e a)` can safely be unlifted in `StateT`, while `finally
> :: IO a -> IO b -> IO a` cannot.
> `monad-control` allows us to unlift both styles. In theory, we could
> write a variant of `lifted-base` that never does state discards, and
> let `try` be more general than `finally`. In other words, this is an
> advantage of `monad-control` over `MonadUnliftIO`. We've avoided
> providing any such extra typeclass in this package though, for two
> reasons:
> * `MonadUnliftIO` is a simple typeclass, easy to explain. We don't
>   want to complicated matters (`MonadBaseControl` is a notoriously
>   difficult to understand typeclass). This simplicity
>   is captured by the laws for `MonadUnliftIO`, which make the
>   behavior of the run functions close to that of the already familiar
>   `lift` and `liftIO`.
> * Having this kind of split would be confusing in user code, when
>   suddenly `finally` is not available to us. We would rather encourage
>   [good practices](https://www.fpcomplete.com/blog/2017/06/readert-design-pattern)
>   from the beginning.
> Another distinction is that `monad-control` uses the `MonadBase`
> style, allowing unlifting to arbitrary base monads. In this package,
> we've elected to go with `MonadIO` style. This limits what we can do
> (e.g., no unlifting to `STM`), but we went this way because:
> * In practice, we've found that the vast majority of cases are dealing
>   with `IO`
> * The split in the ecosystem between constraints like `MonadBase IO`
>   and `MonadIO` leads to significant confusion, and `MonadIO` is by
>   far the more common constraints (with the typeclass existing in
>   `base`)

So is `MonadBaseControl` dead or alive? Any user side example for it?

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.haskell.org/pipermail/haskell-cafe/attachments/20210621/6b93c432/attachment-0001.html>

More information about the Haskell-Cafe mailing list