I'd be over the moon with happiness if I could hang COMPLETE pragmas on polymorphic types.
I have 3 major issues with COMPLETE as it exists.
1.) Is what is mentioned here:
Examples for me come up when trying to build a completely unboxed 'linear' library using backpack. In the end I want/need to supply a pattern synonym that works over, say, all the 2d vector types, extracting their elements, but right now I just get spammed by incomplete coverage warnings.
type family Elem t :: Type
class D2 where
_V2 :: Iso' t (Elem t, Elem t)
pattern V2 :: D2 t => Elem t -> Elem t -> t
pattern V2 a b <- (view _V2 -> (a,b)) where
V2 a b = review _V2 (a,b)
There is no way to hang a COMPLETE pragma on that.
2.) Another scenario that I'd really love to see supported with COMPLETE pragmas is a way to use | notation with them like you can with MINIMAL pragmas.
If you make smart constructors for a dozen constructors in your term type (don't judge me!), you wind up needing 2^12 COMPLETE pragmas to describe all the ways you might mix regular and start constructors today.
{# COMPLETE (Lam | LAM), (Var | VAR), ... #-}
would let you get away with a single such definition. This comes up when you have some kind of monoid that acts on terms and you want to push it down through
the syntax tree invisibly to the user. Explicit substitutions, shifts in position in response to source code edits, etc.
3.) I had one other major usecase where I failed to be able to use a COMPLETE pragma:
type Option a = (# a | (##) #)
pattern Some :: a -> Option a
pattern Some a = (# a | #)
pattern None :: Option a
pattern None = (# | (##) #)
{-# COMPLETE Some, None #-}
These worked _within_ a module, but was forgotten across module boundaries, which forced me to rather drastically change the module structure of a package, but it sounds a lot like the issue being discussed. No types to hang it on in the interface file. With the ability to define unlifted newtypes I guess this last one is less of a concern now?
-Edward