GHC 9.4 regression: derived instance for GADT no longer infers necessary constraints
The syntactic-3.8.4
Hackage library fails to compile with GHC 9.4, whereas it compiled without issue using previous versions of GHC:
[ 1 of 20] Compiling Language.Syntactic.Syntax ( src/Language/Syntactic/Syntax.hs, /home/ryanglscott/Documents/Hacking/Haskell/syntactic-3.8.4/dist-newstyle/build/x86_64-linux/ghc-9.4.2/syntactic-3.8.4/build/Language/Syntactic/Syntax.o, /home/ryanglscott/Documents/Hacking/Haskell/syntactic-3.8.4/dist-newstyle/build/x86_64-linux/ghc-9.4.2/syntactic-3.8.4/build/Language/Syntactic/Syntax.dyn_o )
src/Language/Syntactic/Syntax.hs:207:13: error:
• No instance for (Functor sym1) arising from a use of ‘fmap’
Possible fix:
add (Functor sym1) to the context of
the type signature for:
fmap :: forall a b.
(a -> b) -> (:+:) sym1 sym2 a -> (:+:) sym1 sym2 b
or the instance declaration
• In the first argument of ‘InjL’, namely ‘(fmap f a1)’
In the expression: InjL (fmap f a1)
In an equation for ‘fmap’: fmap f (InjL a1) = InjL (fmap f a1)
When typechecking the code for ‘fmap’
in a derived instance for ‘Functor (sym1 :+: sym2)’:
To see the code I am typechecking, use -ddump-deriv
|
207 | deriving (Functor, Foldable, Traversable)
| ^^^^^^^
src/Language/Syntactic/Syntax.hs:207:13: error:
• No instance for (Functor sym1) arising from a use of ‘<$’
Possible fix:
add (Functor sym1) to the context of
the type signature for:
(<$) :: forall a b. a -> (:+:) sym1 sym2 b -> (:+:) sym1 sym2 a
or the instance declaration
• In the first argument of ‘InjL’, namely ‘((<$) z a1)’
In the expression: InjL ((<$) z a1)
In an equation for ‘<$’: (<$) z (InjL a1) = InjL ((<$) z a1)
When typechecking the code for ‘<$’
in a derived instance for ‘Functor (sym1 :+: sym2)’:
To see the code I am typechecking, use -ddump-deriv
|
207 | deriving (Functor, Foldable, Traversable)
| ^^^^^^^
src/Language/Syntactic/Syntax.hs:207:22: error:
• Could not deduce (Foldable sym1) arising from a use of ‘foldMap’
from the context: Monoid m
bound by the type signature for:
foldMap :: forall m a.
Monoid m =>
(a -> m) -> (:+:) sym1 sym2 a -> m
at src/Language/Syntactic/Syntax.hs:207:22-29
Possible fix:
add (Foldable sym1) to the context of
the type signature for:
foldMap :: forall m a.
Monoid m =>
(a -> m) -> (:+:) sym1 sym2 a -> m
or the instance declaration
• In the expression: foldMap f a1
In an equation for ‘foldMap’: foldMap f (InjL a1) = foldMap f a1
When typechecking the code for ‘foldMap’
in a derived instance for ‘Foldable (sym1 :+: sym2)’:
To see the code I am typechecking, use -ddump-deriv
In the instance declaration for ‘Foldable (sym1 :+: sym2)’
|
207 | deriving (Functor, Foldable, Traversable)
| ^^^^^^^^
src/Language/Syntactic/Syntax.hs:207:22: error:
• No instance for (Foldable sym1) arising from a use of ‘foldr’
Possible fix:
add (Foldable sym1) to the context of
the type signature for:
foldr :: forall a b. (a -> b -> b) -> b -> (:+:) sym1 sym2 a -> b
or the instance declaration
• In the expression: foldr f b2 b1
In the expression: \ b1 b2 -> foldr f b2 b1
In the expression: (\ b1 b2 -> foldr f b2 b1) a1 z
When typechecking the code for ‘foldr’
in a derived instance for ‘Foldable (sym1 :+: sym2)’:
To see the code I am typechecking, use -ddump-deriv
|
207 | deriving (Functor, Foldable, Traversable)
| ^^^^^^^^
src/Language/Syntactic/Syntax.hs:207:22: error:
• No instance for (Foldable sym1) arising from a use of ‘null’
Possible fix:
add (Foldable sym1) to the context of
the type signature for:
null :: forall a. (:+:) sym1 sym2 a -> Bool
or the instance declaration
• In the expression: null a1
In an equation for ‘null’: null (InjL a1) = null a1
When typechecking the code for ‘null’
in a derived instance for ‘Foldable (sym1 :+: sym2)’:
To see the code I am typechecking, use -ddump-deriv
In the instance declaration for ‘Foldable (sym1 :+: sym2)’
|
207 | deriving (Functor, Foldable, Traversable)
| ^^^^^^^^
src/Language/Syntactic/Syntax.hs:207:32: error:
• Could not deduce (Traversable sym1)
arising from a use of ‘traverse’
from the context: Applicative f
bound by the type signature for:
traverse :: forall (f :: * -> *) a b.
Applicative f =>
(a -> f b) -> (:+:) sym1 sym2 a -> f ((:+:) sym1 sym2 b)
at src/Language/Syntactic/Syntax.hs:207:32-42
Possible fix:
add (Traversable sym1) to the context of
the type signature for:
traverse :: forall (f :: * -> *) a b.
Applicative f =>
(a -> f b) -> (:+:) sym1 sym2 a -> f ((:+:) sym1 sym2 b)
or the instance declaration
• In the second argument of ‘fmap’, namely ‘(traverse f a1)’
In the expression: fmap (\ b1 -> InjL b1) (traverse f a1)
In an equation for ‘traverse’:
traverse f (InjL a1) = fmap (\ b1 -> InjL b1) (traverse f a1)
When typechecking the code for ‘traverse’
in a derived instance for ‘Traversable (sym1 :+: sym2)’:
To see the code I am typechecking, use -ddump-deriv
|
207 | deriving (Functor, Foldable, Traversable)
| ^^^^^^^^^^^
Here is a minimized example of the issue:
{-# LANGUAGE DeriveFunctor #-}
module Bug where
data T1 f a = MkT1 (f a)
deriving Functor
data T2 f a where
MkT2 :: f a -> T2 f a
deriving Functor
With GHC 9.2.4, this typechecks:
$ ghc-9.2.4 Bug.hs -fforce-recomp
[1 of 1] Compiling Bug ( Bug.hs, Bug.o )
With GHC 9.4.2, the derived instance for T1
typechecks, but the instance for T2
does not:
$ ghc-9.4.2 Bug.hs -fforce-recomp -ddump-deriv
[1 of 1] Compiling Bug ( Bug.hs, Bug.o )
==================== Derived instances ====================
Derived class instances:
instance GHC.Base.Functor (Bug.T2 f) where
GHC.Base.fmap f_aCj (Bug.MkT2 a1_aCk)
= Bug.MkT2 (GHC.Base.fmap f_aCj a1_aCk)
(GHC.Base.<$) z_aCl (Bug.MkT2 a1_aCm)
= Bug.MkT2 ((GHC.Base.<$) z_aCl a1_aCm)
instance GHC.Base.Functor f => GHC.Base.Functor (Bug.T1 f) where
GHC.Base.fmap f_aCn (Bug.MkT1 a1_aCo)
= Bug.MkT1 (GHC.Base.fmap f_aCn a1_aCo)
(GHC.Base.<$) z_aCp (Bug.MkT1 a1_aCq)
= Bug.MkT1 ((GHC.Base.<$) z_aCp a1_aCq)
Derived type family instances:
Bug.hs:9:12: error:
• No instance for (Functor f) arising from a use of ‘fmap’
Possible fix:
add (Functor f) to the context of
the type signature for:
fmap :: forall a b. (a -> b) -> T2 f a -> T2 f b
or the instance declaration
• In the first argument of ‘MkT2’, namely ‘(fmap f a1)’
In the expression: MkT2 (fmap f a1)
In an equation for ‘fmap’: fmap f (MkT2 a1) = MkT2 (fmap f a1)
When typechecking the code for ‘fmap’
in a derived instance for ‘Functor (T2 f)’:
To see the code I am typechecking, use -ddump-deriv
|
9 | deriving Functor
| ^^^^^^^
Bug.hs:9:12: error:
• No instance for (Functor f) arising from a use of ‘<$’
Possible fix:
add (Functor f) to the context of
the type signature for:
(<$) :: forall a b. a -> T2 f b -> T2 f a
or the instance declaration
• In the first argument of ‘MkT2’, namely ‘((<$) z a1)’
In the expression: MkT2 ((<$) z a1)
In an equation for ‘<$’: (<$) z (MkT2 a1) = MkT2 ((<$) z a1)
When typechecking the code for ‘<$’
in a derived instance for ‘Functor (T2 f)’:
To see the code I am typechecking, use -ddump-deriv
|
9 | deriving Functor
| ^^^^^^^
As shown in the -ddump-deriv
output, the T2
instance is missing a Functor f
constraint that is necessary to typecheck. For whatever reason, the T1
instance has this constraint but the T2
instance does not.