content: -- We used to inline constructor wrapper functions only when fully applied.
  -- This led to unnecessary boxing when partially applying to unpacked fields.
  
  module Main where
  import Control.DeepSeq
  import Data.Functor.Identity
  import Control.Exception (evaluate)
  
  data AList = Cons !Int !Int !Int !Int !Int !Int !Int !Int !Int AList | Nil
  
  -- We need to write this instance manually because the Generic-derived
  -- instance allocates a ton of intermediate junk, obscuring the interesting
  -- differences.
  instance NFData AList where
    rnf Nil = ()
    rnf (Cons _1 _2 _3 _4 _5 _6 _7 _8 _9 xs) = rnf xs
  
  -- If GHC is allowed to specialize it to Identity, the partial application of
  -- Cons will become a fully saturated one, defeating the test. So we NOINLINE
  -- it.
  buildalist :: Applicative f => Int -> f AList
  buildalist n
    | n <= 0 = pure Nil
    | otherwise = Cons n (n+1) (n+2) (n+3) (n+4) (n+5) (n+6) (n+7) (n+8) <$>
                    buildalist (n - 1)
  {-# NOINLINE buildalist #-}
  
  main = evaluate . rnf . runIdentity $ buildalist 100000
  