Partially applied constructors with unpacked fields simplified badly
When a constructor is partially applied to at least one unpacked field, the simplifier produces pretty lousy results.
data Foo a = Foo !Int a
silly :: ((a -> Foo a) -> r) -> r
silly f = f (Foo 3)
compiles to
-- RHS size: {terms: 9, types: 7, coercions: 0}
$WFoo :: forall a. Int -> a -> Foo a
$WFoo =
\ (@ a_aqI) (dt_ayl :: Int) (dt_aym :: a_aqI[sk:1]) ->
case dt_ayl of { I# dt_ayn -> Foo dt_ayn dt_aym }
-- RHS size: {terms: 2, types: 0, coercions: 0}
silly2 :: Int
silly2 = I# 3#
-- RHS size: {terms: 3, types: 3, coercions: 0}
silly1 :: forall a. a -> Foo a
silly1 = \ (@ a_ayG) -> $WFoo silly2
-- RHS size: {terms: 5, types: 9, coercions: 0}
silly :: forall a r. ((a -> Foo a) -> r) -> r
silly =
\ (@ a_ayG) (@ r_ayH) (f_axY :: (a -> Foo a) -> r) -> f_axY silly1
That is, GHC represents Foo 3
as a closure containing a boxed Int
. Manually eta-expanding would fix it.
silly :: ((a -> Foo a) -> r) -> r
silly f = f (\x -> Foo 3 x)
compiles to
-- RHS size: {terms: 5, types: 4, coercions: 0}
silly1 :: forall a. a -> Foo a
silly1 = \ (@ a_ayO) (x_ay9 :: a) -> Foo 3# x_ay9
-- RHS size: {terms: 5, types: 9, coercions: 0}
silly :: forall a r. ((a -> Foo a) -> r) -> r
silly =
\ (@ a_ayO) (@ r_ayP) (f_ay8 :: (a -> Foo a) -> r) -> f_ay8 silly1
in which the Int
is unpacked into the closure. This transformation is valid whenever the value to be stored unpacked is known not to be bottom, and is certainly a good idea if it's known to have been forced.