- | Just co2 <- splitSymCoercion_maybe co = co2
- -- sym (sym co) --> co
- | Just (co1, arg_tys) <- splitTyConApp_maybe co
- , not (isCoercionTyCon co1) = mkTyConApp co1 (map mkSymCoercion arg_tys)
- -- we can drop the sym for a TyCon
- -- sym (ty [t1, ..., tn]) --> ty [sym t1, ..., sym tn]
- | (co1, arg_tys) <- splitAppTys co
- , isTyVarTy co1 = mkAppTys (maybe_drop co1) (map mkSymCoercion arg_tys)
- -- sym (tv [t1, ..., tn]) --> tv [sym t1, ..., sym tn]
- -- if tv type variable
- -- sym (cv [t1, ..., tn]) --> (sym cv) [sym t1, ..., sym tn]
- -- if cv is a coercion variable
- -- fall through if head is a CoercionTyCon
- | Just (co1, co2) <- splitTransCoercion_maybe co
+ | Just co' <- coreView co = mkSymCoercion co'
+
+mkSymCoercion (ForAllTy tv ty) = ForAllTy tv (mkSymCoercion ty)
+mkSymCoercion (AppTy co1 co2) = AppTy (mkSymCoercion co1) (mkSymCoercion co2)
+mkSymCoercion (FunTy co1 co2) = FunTy (mkSymCoercion co1) (mkSymCoercion co2)
+
+mkSymCoercion (TyConApp tc cos)
+ | not (isCoercionTyCon tc) = mkTyConApp tc (map mkSymCoercion cos)
+
+mkSymCoercion (TyConApp tc [co])
+ | tc `hasKey` symCoercionTyConKey = co -- sym (sym co) --> co
+ | tc `hasKey` leftCoercionTyConKey = mkLeftCoercion (mkSymCoercion co)
+ | tc `hasKey` rightCoercionTyConKey = mkRightCoercion (mkSymCoercion co)
+
+mkSymCoercion (TyConApp tc [co1,co2])
+ | tc `hasKey` transCoercionTyConKey