Note [FunTyFlag]

GHC/Types/Var.hs:558 compiler 2 tickets

FunTyFlag is used principally in the FunTy constructor of Type.
  FunTy FTF_T_T t1 t2   means   t1 -> t2
  FunTy FTF_C_T t1 t2   means   t1 => t2
  FunTy FTF_T_C t1 t2   means   t1 -=> t2
  FunTy FTF_C_C t1 t2   means   t1 ==> t2

However, the FunTyFlag in a FunTy is just redundant, cached
information.  In (FunTy { ft_af = af, ft_arg = t1, ft_res = t2 })
  
  (isPredTy t1)   (isPredTy ty)     FunTyFlag
  
     False           False         FTF_T_T
     False           True          FTF_T_C
     True            False         FTF_C_T
     True            True          FTF_C_C
where isPredTy is defined in GHC.Core.Predicate, and sees if t1's
kind is Constraint.  See GHC.Core.Type.chooseFunTyFlag, and
GHC.Core.Predicate Note [Types for coercions, predicates, and evidence]

The term (Lam b e) doesn't carry an FunTyFlag; instead it uses
mkFunctionType when we want to get its types; see mkLamType.  This is
just an engineering choice; we could cache here too if we wanted.

Why bother with all this? After all, we are in Core, where (=>) and
(->) behave the same.  We maintain this distinction throughout Core so
that we can cheaply and conveniently determine
* How to print a type
* How to split up a type: tcSplitSigmaTy
* How to specialise it (over type classes; GHC.Core.Opt.Specialise)

For the specialisation point, consider
(\ (d :: Ord a). blah).  We want to give it type
           (Ord a => blah_ty)
with a fat arrow; that is, using mkInvisFunTy, not mkVisFunTy.
Why?  Because the /specialiser/ treats dictionary arguments specially.
Suppose we do w/w on 'foo', thus (#11272, #6056)
   foo :: Ord a => Int -> blah
   foo a d x = case x of I# x' -> $wfoo @a d x'

   $wfoo :: Ord a => Int# -> blah

Now, at a call we see (foo @Int dOrdInt).  The specialiser will
specialise this to $sfoo, where
   $sfoo :: Int -> blah
   $sfoo x = case x of I# x' -> $wfoo @Int dOrdInt x'

Now we /must/ also specialise $wfoo!  But it wasn't user-written,
and has a type built with mkLamTypes.

Conclusion: the easiest thing is to make mkLamType build
            (c => ty)
when the argument is a predicate type.  See GHC.Core.TyCo.Rep
Note [Types for coercions, predicates, and evidence]

References 1

Referenced by 7