GHC 9.6.1 rejects previously working code

The following code compiles with older compilers but does not compile with GHC 9.6.1: {-# LANGUAGE KindSignatures #-} module A () where import Control.Monad.IO.Class import Control.Monad.Trans.Class data T (m :: * -> *) a = T instance Functor (T m) where fmap f T = undefined instance Applicative (T m) where pure = undefined (<*>) = undefined instance MonadIO m => Monad (T m) where return = pure (>>=) = undefined instance MonadTrans T where lift = undefined It fails with the following error: xx.hs:20:10: error: [GHC-39999] • Could not deduce ‘MonadIO m’ arising from the head of a quantified constraint arising from the superclasses of an instance declaration from the context: Monad m bound by a quantified context at xx.hs:20:10-21 Possible fix: add (MonadIO m) to the context of a quantified context • In the instance declaration for ‘MonadTrans T’ | 20 | instance MonadTrans T where | ^^^^^^^^^^^^ What is the correct resolution for this? -harendra

On Wed, Apr 12, 2023 at 02:32:43PM +0530, Harendra Kumar wrote:
instance MonadIO m => Monad (T m) where return = pure (>>=) = undefined
instance MonadTrans T where lift = undefined
I guess it's nothing to do with 9.6 per se, but rather the difference between * https://hackage.haskell.org/package/transformers-0.5.6.2/docs/Control-Monad-... * https://hackage.haskell.org/package/transformers-0.6.1.0/docs/Control-Monad-... I'm not sure I can see any solution for this. A monad transformer `T` must give rise to a monad `T m` regardless of what `m` is. If `T m` is only a monad when `MonadIO m` then `T` can't be a monad transformer (under transformers 0.6). Tom

Indeed, this is included in the GHC 9.6.x Migration Guide https://gitlab.haskell.org/ghc/ghc/-/wikis/migration/9.6#transformers-06-new.... Unfortunately, I’m also not sure there is a solution for this particular where (T m) is only a Monad if m instances MonadIO. As Tom explained, under transformers 0.6 `T` no longer is a monad transformer. A few workarounds I can think of: - No longer instance `MonadTrans T`, and use a instance `MonadIO m => MonadIO (T m)` instead. Rationale: if you always require `m` to be `MonadIO`, perhaps the ability to always lift an `m` to `T m` with `liftIO` is sufficient. - Add the `MonadIO` instance to the `m` field of `T`, GADT style, `data T m a where T :: MonadIO m => m -> T m a` Rational: You would no longer need `MonadIO` in the `Monad` instance, which will make it possible to instance `MonadTrans`. - Redefine your own `lift` regardless of `MonadTrans` Good luck! Rodrigo
On 12 Apr 2023, at 10:10, Tom Ellis
wrote: On Wed, Apr 12, 2023 at 02:32:43PM +0530, Harendra Kumar wrote:
instance MonadIO m => Monad (T m) where return = pure (>>=) = undefined
instance MonadTrans T where lift = undefined
I guess it's nothing to do with 9.6 per se, but rather the difference between
* https://hackage.haskell.org/package/transformers-0.5.6.2/docs/Control-Monad-...
* https://hackage.haskell.org/package/transformers-0.6.1.0/docs/Control-Monad-...
I'm not sure I can see any solution for this. A monad transformer `T` must give rise to a monad `T m` regardless of what `m` is. If `T m` is only a monad when `MonadIO m` then `T` can't be a monad transformer (under transformers 0.6).
Tom _______________________________________________ ghc-devs mailing list ghc-devs@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs

Thanks Tom and Rodrigo.
That clarifies the problem. We will need to think which solution makes
better sense.
On Wed, 12 Apr 2023 at 15:01, Rodrigo Mesquita
Indeed, this is included in the GHC 9.6.x Migration Guide https://gitlab.haskell.org/ghc/ghc/-/wikis/migration/9.6#transformers-06-new... .
Unfortunately, I’m also not sure there is a solution for this particular where (T m) is only a Monad if m instances MonadIO. As Tom explained, under transformers 0.6 `T` no longer is a monad transformer.
A few workarounds I can think of:
- No longer instance `MonadTrans T`, and use a instance `MonadIO m => MonadIO (T m)` instead. Rationale: if you always require `m` to be `MonadIO`, perhaps the ability to always lift an `m` to `T m` with `liftIO` is sufficient.
- Add the `MonadIO` instance to the `m` field of `T`, GADT style, `data T m a where T :: MonadIO m => m -> T m a` Rational: You would no longer need `MonadIO` in the `Monad` instance, which will make it possible to instance `MonadTrans`.
- Redefine your own `lift` regardless of `MonadTrans`
Good luck! Rodrigo
On 12 Apr 2023, at 10:10, Tom Ellis < tom-lists-haskell-cafe-2017@jaguarpaw.co.uk> wrote:
On Wed, Apr 12, 2023 at 02:32:43PM +0530, Harendra Kumar wrote:
instance MonadIO m => Monad (T m) where return = pure (>>=) = undefined
instance MonadTrans T where lift = undefined
I guess it's nothing to do with 9.6 per se, but rather the difference between
* https://hackage.haskell.org/package/transformers-0.5.6.2/docs/Control-Monad-...
* https://hackage.haskell.org/package/transformers-0.6.1.0/docs/Control-Monad-...
I'm not sure I can see any solution for this. A monad transformer `T` must give rise to a monad `T m` regardless of what `m` is. If `T m` is only a monad when `MonadIO m` then `T` can't be a monad transformer (under transformers 0.6).
Tom _______________________________________________ ghc-devs mailing list ghc-devs@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs
_______________________________________________ ghc-devs mailing list ghc-devs@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs

Out of curiosity, why do you require the `MonadIO` on the `Monad` instance? On 4/12/23 12:42, Harendra Kumar wrote:
Thanks Tom and Rodrigo.
That clarifies the problem. We will need to think which solution makes better sense.
On Wed, 12 Apr 2023 at 15:01, Rodrigo Mesquita
wrote: Indeed, this is included in the GHC 9.6.x Migration Guide https://gitlab.haskell.org/ghc/ghc/-/wikis/migration/9.6#transformers-06-new....
Unfortunately, I’m also not sure there is a solution for this particular where (T m) is only a Monad if m instances MonadIO. As Tom explained, under transformers 0.6 `T` no longer is a monad transformer.
A few workarounds I can think of:
- No longer instance `MonadTrans T`, and use a instance `MonadIO m => MonadIO (T m)` instead. Rationale: if you always require `m` to be `MonadIO`, perhaps the ability to always lift an `m` to `T m` with `liftIO` is sufficient.
- Add the `MonadIO` instance to the `m` field of `T`, GADT style, `data T m a where T :: MonadIO m => m -> T m a` Rational: You would no longer need `MonadIO` in the `Monad` instance, which will make it possible to instance `MonadTrans`.
- Redefine your own `lift` regardless of `MonadTrans`
Good luck! Rodrigo
On 12 Apr 2023, at 10:10, Tom Ellis
wrote: On Wed, Apr 12, 2023 at 02:32:43PM +0530, Harendra Kumar wrote:
instance MonadIO m => Monad (T m) where return = pure (>>=) = undefined
instance MonadTrans T where lift = undefined
I guess it's nothing to do with 9.6 per se, but rather the difference between
* https://hackage.haskell.org/package/transformers-0.5.6.2/docs/Control-Monad-...
* https://hackage.haskell.org/package/transformers-0.6.1.0/docs/Control-Monad-...
I'm not sure I can see any solution for this. A monad transformer `T` must give rise to a monad `T m` regardless of what `m` is. If `T m` is only a monad when `MonadIO m` then `T` can't be a monad transformer (under transformers 0.6).
Tom _______________________________________________ ghc-devs mailing list ghc-devs@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs
_______________________________________________ ghc-devs mailing list ghc-devs@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs
_______________________________________________ ghc-devs mailing list ghc-devs@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs
participants (4)
-
Georgi Lyubenov
-
Harendra Kumar
-
Rodrigo Mesquita
-
Tom Ellis