Use injective type families (decomposition) when dealing with givens
Consider this code:
type family Id a = r | r -> a
id :: (Id a ~ Id b) => a -> b
id x = x
GHC currently rejects it because it does not use type family injectivity information when dealing with the given constraints.
And yet Coercion
has a form for representing such coercions, namely "nth" (written SelCo
in GHC). We could say
co : F s1..sn ~ F t1..tn
F is injective in its i'th argument
-----------------------------------
SelCo (Tc i) co : si ~ ti
Indeed Lint already accepts such SelCo
s:
lintCoercion the_co@(SelCo cs co)
= do { co' <- lintCoercion co
; let (Pair s t, co_role) = coercionKindRole co'
; if -- forall (both TyVar and CoVar)
...
-- TyCon
| Just (tc_s, tys_s) <- splitTyConApp_maybe s
, Just (tc_t, tys_t) <- splitTyConApp_maybe t
, tc_s == tc_t
, SelTyCon n r0 <- cs
, isInjectiveTyCon tc_s co_role
-- see Note [SelCo and newtypes] in GHC.Core.TyCo.Rep
, tys_s `equalLength` tys_t
, tys_s `lengthExceeds` n
-> do { lintRole the_co (tyConRole co_role tc_s n) r0
; return (SelCo cs co') }
Note that isInjectiveTyCon
! An injective type family is accepted here. (But only if it is injective in all arguments, which is stronger than we need.)
Allowing this would be user facing change, hence needing a GHC proposal. But it'd be very simple to implement.
@rae any views on how this might impact soundness?
Trac metadata
Trac field | Value |
---|---|
Version | 7.10.2 |
Type | FeatureRequest |
TypeOfFailure | OtherFailure |
Priority | normal |
Resolution | Unresolved |
Component | Compiler (Type checker) |
Test case | |
Differential revisions | |
BlockedBy | |
Related | #6018 (closed) |
Blocking | |
CC | |
Operating system | |
Architecture |
Edited by Simon Peyton Jones