content: {- This example illustrates a nasty case of "vacuous" abstraction
     It comes from Cabal library Distribution.Simple.Utils
  
  Consider this
  
    type HCS = (?callStack :: CallStack)
    wcs :: forall a. (HCS => a) -> a
    foo :: Int
    ($) :: forall p q. (p->q) -> p -> q
  
  The call:      wcs $ foo
  
  From QL on the first arg of $ we instantiate wcs with a:=kappa.  Then
  we can work out what p and q must instantiate to.  (the (p->q) arg of
  ($) is guarded): get p := (HCS => kappa), q := kappa
  
  But alas, the second arg of $, namely foo, satisfies our
  fiv(rho_r)=empty condition.  (Here rho_r is Int.)  So we try to mgu(
  HCS => kappa, Int ), and fail.
  
  The basic problem is this: we said in 5.4 of the Quick Look paper we
  didn’t about vacuous type abstraction, but we clearly do care about
  type-class abstraction.
  
  How does this work in GHC today, with the built-in rule?  It works
  because we are order-dependent: we look at the first argument first.
  
  The same would work here.  If we applied the QL substitution as we go,
  by the time we got to the second argument, the expected type would
  look like (HCS => kappa), and we would abandon QL on it (App-lightning
  only applies to rho).  But the price is order-dependence.
  -}
  
  module CabalEx where
  
  import GHC.Stack( withFrozenCallStack )
  
  -- withFrozenCallStack :: HasCallStack
  --                     => ( HasCallStack => a )
  --                     -> a
  
  printRawCommandAndArgsAndEnv :: Int -> IO ()
  printRawCommandAndArgsAndEnv = error "urk"
  
  printRawCommandAndArgs :: Int -> IO ()
  printRawCommandAndArgs verbosity
    = withFrozenCallStack $ printRawCommandAndArgsAndEnv verbosity
  