Fragile RULES in GHC.Float
Consider a method like
class ... => RealFrac a where
floor :: Integral b => a -> b
So floor :: forall a. RealFrac a => forall b. Integral b => a -> b
.
Notice the two dictionary arguments.
Now suppose we want to hand-write specialised code for
(floor @Double d1 @Int d2)
.
We used to have
RULE "floor/Double->Int" floor = floorDoubleInt
where GHC.Float.RealFracMethods
defines
floorDoubleInt :: Double -> Int
This RULE in full is
RULE "floor/Double->Int" forall d1 d2.
floor @Double d1 @Int d2 = floorDoubleInt
But it's best not to write one rule for this entire step. I found cases
(in nofib/readl/gamteb/Utils.hs
, function fiRem
) where we floated
out the (floor @Double d1) part, so the above two-argument rule didn't fire.
Instead the class-op rule fired. Boo!
Actually this only happens if we float out over-saturated applications
(the floatOutOverSatApps
flag in FloatOutSwitches
, which currently we never
do. So I don't think this patch will change a thing. But it makes GHC robust
to floating out over-saturated applications, which I am experimenting with elsewhere,
so I want to fix this infelicity first.