Derive instances without making the user explicitly demand constraints the compiler already knows about
Motivation
Consider the following code:
{-# LANGUAGE
KindSignatures
, DataKinds
, TypeFamilies
, StandaloneDeriving
, PartialTypeSignatures
, TypeFamilyDependencies
, FlexibleInstances
, FlexibleContexts
, UndecidableInstances
, TypeApplications
#-}
module Main where
data Idx = Foo | Bar
type family F (a :: Idx) b where
F Foo String = Int
F Foo Int = String
F Bar String = String
F Bar Int = Int
data Test (i :: Idx) = Test { userId :: F i String, userName :: F i Int }
-- deriving Show -- this won't work
deriving instance
-- _ => -- this won't work either
(Show (F i String), Show (F i Int)) => -- this works
Show (Test i)
main :: IO ()
main = print $ Test @Foo (1 :: Int) "foo"
(sorry if the example has a few red herrings, just translating something from slack).
You can see that the constraints in the standalone deriving declaration duplicate the fields of the Test
ADT. The compiler is actually aware of all the constraints it would need to demand in order to provide a derived instance of Show
for Test i
, it just won't go ahead and infer them.
Proposal
Provide some mechanism (doesn't necessarily have to be data Test = ... deriving Show
or deriving instance _ => Show (Test i)
) that allows us to just say "yeah, about those missing constraints, just go ahead and demand them and give me an instance".
NB: The type family stuff might be a little bit of a red herring, I think the inability to derive data Test f i = Test { userId :: f i String, userName :: f i Int } deriving Show
is the same underlying issue.