Note [ForAllTy and type equality]
When we compare (ForAllTy (Bndr tv1 vis1) ty1)
and (ForAllTy (Bndr tv2 vis2) ty2)
what should we do about `vis1` vs `vis2`?
We had a long debate about this: see #22762 and GHC Proposal 558.
Here is the conclusion.
* In Haskell, we really do want (forall a. ty) and (forall a -> ty) to be
distinct types, not interchangeable. The latter requires a type argument,
but the former does not. See GHC Proposal 558.
* We /really/ do not want the typechecker and Core to have different notions of
equality. That is, we don't want `tcEqType` and `eqType` to differ. Why not?
Not so much because of code duplication but because it is virtually impossible
to cleave the two apart. Here is one particularly awkward code path:
The type checker calls `substTy`, which calls `mkAppTy`,
which calls `mkCastTy`, which calls `isReflexiveCo`, which calls `eqType`.
* Moreover the resolution of the TYPE vs CONSTRAINT story was to make the
typechecker and Core have a single notion of equality.
* So in GHC:
- `tcEqType` and `eqType` implement the same equality
- (forall a. ty) and (forall a -> ty) are distinct types in both Core and typechecker
- That is, both `eqType` and `tcEqType` distinguish them.
* But /at representational role/ we can relate the types. That is,
(forall a. ty) ~R (forall a -> ty)
After all, since types are erased, they are represented the same way.
See Note [ForAllCo] and the typing rule for ForAllCo given there
* What about (forall a. ty) and (forall {a}. ty)? See Note [Comparing visibility]. References 2
- Comparing visibility GHC.Core.TyCo.Compare
- ForAllCo GHC.Core.TyCo.Rep
Referenced by 14
- GHC.Core.TyCo.Compare call site ×6
- ForAllCo GHC.Core.TyCo.Rep ×2
- Flag cast in data con wrappers GHC.Core.DataCon
- GHC.Core.Map.Type call site
- Comparing visibility GHC.Core.TyCo.Compare
- Required foralls in Core GHC.Core.TyCo.Rep
- GHC.Tc.Solver.Equality call site
- Deep subsumption and required foralls GHC.Tc.Utils.Unify