Derived enum instances should support list fusion.
Motivation
List fusion improves performance so is desireable.
However it's currently not supported by Enum instances when derived by GHC.
Consider this case:
data T = A | B | C | D | E | F | G | H | I | J | K deriving (Enum)
bar = [A .. E]
If a use site maps over bar we would hope this would fuse with the enumeration.
In practice however we end up with Core like this:
Rec {
-- RHS size: {terms: 34, types: 21, coercions: 0, joins: 0/0}
MyEnum.$wgo [InlPrag=NOUSERINLINE[2], Occ=LoopBreaker]
:: GHC.Prim.Int# -> (# T, [T] #)
[GblId, Arity=1, Str=<L,U>, Unf=OtherCon []]
MyEnum.$wgo
= \ (w_s2SI :: GHC.Prim.Int#) ->
(# case GHC.Prim.>=# w_s2SI 0# of {
__DEFAULT -> MyEnum.$wlvl w_s2SI;
1# ->
case GHC.Prim.<=# w_s2SI 10# of {
__DEFAULT -> MyEnum.$wlvl w_s2SI;
1# -> GHC.Prim.tagToEnum# @ T w_s2SI
}
},
case w_s2SI of wild_X13 {
__DEFAULT ->
case MyEnum.$wgo (GHC.Prim.+# wild_X13 1#) of
{ (# ww1_s2SN, ww2_s2SO #) ->
GHC.Types.: @ T ww1_s2SN ww2_s2SO
};
4# -> GHC.Types.[] @ T
} #)
end Rec }
-- RHS size: {terms: 7, types: 10, coercions: 0, joins: 0/0}
bar :: [T]
[GblId,
Unf=Unf{Src=<vanilla>, TopLvl=True, Value=False, ConLike=False,
WorkFree=False, Expandable=False, Guidance=IF_ARGS [] 40 30}]
bar
= case MyEnum.$wgo 0# of { (# ww1_s2SN, ww2_s2SO #) ->
GHC.Types.: @ T ww1_s2SN ww2_s2SO
}
Which won't support list fusion. The recursive go function doesn't get a unfolding at all.
Even if it did it would need to be implemented differently to support fusion.
Proposal
The implementation should be changed to make bar a good producer for list fusion.