
Hi, Motivating example: I have an open sum type (Variant, or V) which can be used to store values of different types: x,y :: V '[String,Int] x = V "test" y = V @Int 10 f :: V '[String,Int] -> String f = \case V s -> "Found string: " ++ s V (i :: Int) -> "Found int: " ++ show (i+10) V is a pattern synonym defined like this (you don't need to understand the details): pattern V :: forall c cs. (c :< cs) => c -> Variant cs pattern V x <- (fromVariant -> Just x) where V x = toVariant x Where the (:<) constraint checks that we are not doing anything wrong: z :: V '[String,Int] z = V @Float 10 Test.hs:15:5: error: • `Float' is not a member of '[String, Int] • In the expression: V @Float 10 In an equation for ‘z’: z = V @Float 10 f :: V '[String,Int] -> String f = \case ... V (i :: Float) -> "Found float: " ++ show i Test.hs:20:4: error: • `Float' is not a member of '[String, Int] • In the pattern: V (i :: Float) In a case alternative: V (i :: Float) -> "Found float: " ++ show i So far so good, it works well. Now the issues: 1) The case-expression in "f" is reported as non-exhaustive 2) We have to disambiguate the type of "10" in the definition of "y" and in the match "(V (i :: Int))" Both of these issues are caused by the fact that even with the (c :< cs) constraint, GHC doesn't know/use the fact that the type "c" is really one of the types in "cs". Would it make sense to add the following built-in "isOneOf" constraint: ∈ :: k -> [k] ->Constraint pattern V :: forall c cs. (c :< cs, c ∈ cs) => c -> Variant cs 1) GHC could infer pattern completeness information when the V pattern is used depending on the type list "cs" 2) GHC might use the "c ∈ cs" constraint in the last resort to infer "c" if it remains ambiguous: try to type-check with c~c' forall c' in cs and if there is only one valid and unambiguous c', then infer c~c'. Has it already been considered? I don't know how hard it would be to implement nor if it is sound to add something like this. 1 seems simpler/safer than 2, though (it is similar to a new kind of COMPLETE pragma), and it would already be great! Any thoughts? Best regards, Sylvain