Thanks for the bug report. I remember trying something like this too and being surprised it didn't work.
Now, here the problem has to do with specifying an additional constraint for a rule. If we write
{-# RULES "foo -> bar" forall x. foo x = bar x #-}
we get the error:
* No instance for (KnownNat m) arising from a use of `bar' Possible fix: add (KnownNat m) to the context of the RULE "foo -> bar" * In the expression: bar x When checking the rewrite rule "foo -> bar" |16 | {-# RULES "foo -> bar" forall x. foo x = bar x #-} | ^^^
The error is fair enough, but it's unclear how to go about adding KnownNat m to the context, given the special syntax of rewrite rules. You went with what seems to be the only option, which is to add it as a context to x, but I think that just gets GHC confused because now it expects x to take one value argument (the dictionary), and thus fails to match against Proxy @Nat @1 which is not of the right form (no value arguments).
I'm not too familiar with the syntax of rewrite rules myself, so perhaps someone else (e.g. @simonpj) can chime in and give a better explanation of the problem/possible solutions.
I don't think there is much hope writing rewriting an application of foo to an application of bar because the arguments of foo don't contain enough information (ie no KnownNat dictionary) to write to an application of bar.
OTOH, the rule as written doesn't seem to make much sense, in core I would expect the argument x to be represented by a function due to the type containing a => but somehow this is accepted as an argument to foo and bar.
The reason the for the structure of the rule can be boiled down the inferred type of the following program:
check (x :: KnownNat m => Proxy m) = bar x
which gets inferred type
check :: KnownNat m => (KnownNat m => Proxy m) -> Int
but of course if you write
check (x :: forall m . KnownNat m => Proxy m) = bar x
then that gets rejected (correctly) with a type error
Test.hs:9:49: error: • No instance for (KnownNat m0) arising from a use of ‘bar’ • In the expression: bar x In an equation for ‘check’: check (x :: forall m. KnownNat m => Proxy m) = bar x |9 | check (x :: forall m . KnownNat m => Proxy m) = bar x |