Is there any way to write a type family that sometimes evaluates to a constrained type such as C a => T?
This question arose when I was writing the following type family:
type family Function (cs :: [Constraint]) (as :: [Type]) (r :: Type) :: Type where
Function (c ': cs) as r = c => Function cs as r
Function '[] (a ': as) r = a -> Function '[] as r
Function '[] '[] r = r
The goal was that Function '[Integral a, Show b] '[String, b, a] (IO ()) would evaluate to Integral a => Show b => String -> b -> a -> IO (). However, instead, I get the error
• Illegal qualified type: c => Function cs as r
• In the equations for closed type family ‘Function’
In the type family declaration for ‘Function’
I tried using Show c => Function cs as r to see if the issue was with the bare c, but that didn't seem to make a difference. I've tried this with GHC2021 plus the extensions ConstraintKinds, DataKinds, RankNTypes, TypeFamilies, and UndecidableInstances, but I'm happy to add any other language extensions as well if they'll make a difference.
Is there any way to do this? If not, why isn't it possible?
This compiles. The trick is splitting the constraint part and the type part.