Skip to content

GHC 9.6 incorrect redundant constraint warning with generalized newtype deriving

Summary

GHC 9.6 introduces a new -Wredundant-constraints warning in derived code. This is not present in 9.4. It is also not present in a manually written instance. I believe that the constraint is actually necessary.

Steps to reproduce

Compile the following code with GHC 9.6, mtl-2.3.1 and transformers-0.6.1.0:

{-# LANGUAGE DerivingStrategies #-}
{-# LANGUAGE GeneralizedNewtypeDeriving #-}
{-# LANGUAGE QuantifiedConstraints #-}
{-# LANGUAGE InstanceSigs #-}
{-# LANGUAGE TypeApplications #-}
{-# LANGUAGE ScopedTypeVariables #-}

module Bug where

import Control.Monad.Reader
import Control.Applicative
import Data.Coerce

newtype NullDbT m a = NullDbT {unNullDbT :: ReaderT Int m a}
  deriving newtype
    ( Functor
    , Applicative
    , Alternative
    , Monad
    , MonadTrans -- GHC complains the monad constraint is redundant
    )

class (forall m. Monad m => Monad (t m)) => C t where
  myLift :: Monad m => m a -> t m a

instance C NullDbT where 
  -- Monad constraint is required (GHC errors if it is not present, with either implementation)
  myLift :: forall m a . Monad m => m a -> NullDbT m a
  --myLift x = NullDbT (lift @(ReaderT Int) x)
  myLift = coerce @(m a -> ReaderT Int m a) @(m a -> NullDbT m a) (lift @(ReaderT Int))

Expected behavior

I expect consistent warnings/errors between the derived code and a manually written copy. In particular here, I believe that the constraint is necessary, since it is needed for the lift @(ReaderT Int) call.

Environment

  • GHC version used: 9.6

Optional:

  • Operating System: NixOS
  • System Architecture: x86_64
Edited by Ben Price
To upload designs, you'll need to enable LFS and have an admin enable hashed storage. More information