Missed specialisation opportunities
I'm going to document one way (the only way I think) in which we can miss specialisation opportunities via class methods.
Background
g :: Ord a => blahg
g = /\ a \(d::Ord a). ...
f :: Ord a => blahf
f = /\ a \(d::Ord a). ...(g a d)...
....f @Int dOrdInt...
From the call f @Int dOrdInt
we specialise f
to get
$sf :: blahf[Int/a]
$sf = ...(g Int dOrdInt)...
Now, the specialiser sees this specialised call to g
, arising from the specialised
RHS of $sf
, and hence specialises g
as well.
The lost opportunity
Suppose now that we had
class C a where
foo :: forall b. Ord b => blah
...
fooInt :: forall b. Ord b => blah[Int/a]
fooInt = ...
-- instance C Int where
-- foo = fooInt
dCInt :: CInt
dCInt = MkC fooInt ...
f :: C a => blahf
f = /\ a \(d::C a). ...(foo a d)...
...f @Int dCInt @Char dOrdChar...
Notice that foo
has local, overloaded polymorphism, so that
foo :: forall a. C a => forall b. Ord b => blah
That is what gives rise to the lost opportunity.
We specialise f
as before:
$sf :: blah[Int/a]
$sf = ...(foo @Int dCInt @Char dOrdChar)...
But now we don't currently go any further. Yet later, when the simplifer runs, we'll run the built-in method-selector RULE to give
$sf = ...(fooInt @Char dOrdChar)...
and now we see that we should have specialised fooInt
.
What's the solution? Not trying to specialise foo
: it's only a method selector. Rather,
we'd need the Specialiser to run that built-in RULE on the fly, just as it does a lot
of substitution on the fly, to expose new specialision opportunities.
I don't think this would be hard to achieve, in the code for specExpr
, here
specExpr env expr@(App {})
= go expr []
where
go (App fun arg) args = do (arg', uds_arg) <- specExpr env arg
(fun', uds_app) <- go fun (arg':args)
return (App fun' arg', uds_arg `plusUDs` uds_app)
go (Var f) args = case specVar env f of
Var f' -> return (Var f', mkCallUDs env f' args)
e' -> return (e', emptyUDs) -- I don't expect this!
go other _ = specExpr env other
But it's not trivial either. I'm not sure if it's worth it.