Class op rules

Simon Peyton Jones simonpj at
Fri Mar 6 23:02:41 UTC 2020

Here’s how it works:

  *   The rewrite from    opi (D m1 … mn)   -->   mi

is done by a BuiltinRule: see MkId.mkDictSelId, and the BuiltinRule that is made there.

  *   At the moment, BuiltinRules are always active (in all phases), see GHC.Core.ruleActivation.  To allow them to be selectively active, we’d have to give them a ru_act fiels, like ordinary Rules.  That would not be hard.

  *   The phases go
     *   InitialPhase
     *   2
     *   1
     *   0

  *   We could make classop rules active only in phase 1 and 0, say.   I don’t know what the consequences would be; running the classop to pick a method out of a dictionary in turn reveals new function applications that might want to work in phase 2, say.

  *   Of course you can always add more phases, but that adds compile time.

  *   Would you want the classop phase to be fixed for every classop? Or controllable for each classop individually.  E.g.   class C a where {  op :: <bype>  {-# INLINE [2] op #-} }

Here the intent is that, since the pragmas is in the class decl, the pragma applies to the method selector.

I remember Conal raising this before, but I’ve forgotten the resolution.  I’m entirely open to changes here, if someone is willing to do the work, including checking for consequences.


From: ghc-devs <ghc-devs-bounces at> On Behalf Of Conal Elliott
Sent: 06 March 2020 17:37
To: Christiaan Baaij <christiaan.baaij at>
Cc: ghc-devs <ghc-devs at>
Subject: Re: Class op rules

Thank you for raising this issue, Christiaan! The current policy (very early class-op inlining) is a major difficulty and the main source of fragility in my compiling-to-categories implementation. I have a tediously programmed and delicately balanced collection of techniques to intercept and transform class ops to non-ops early and then transform back late for elimination, but it doesn't work in all situations. Since class operations roughly correspond to operations in various algebraic abstractions---interfaces with laws---I often want to exploit exactly those laws as rewrite rules, and yet those rules currently cannot be used dependably.  - Conal

On Fri, Mar 6, 2020 at 7:22 AM Christiaan Baaij <christiaan.baaij at<mailto:christiaan.baaij at>> wrote:

The other day I was experimenting with RULES and got this warning:

src/Clash/Sized/Vector.hs:2159:11: warning: [-Winline-rule-shadowing]
    Rule "map Pack" may never fire
      because rule "Class op pack" for ‘pack’ might fire first
    Probable fix: add phase [n] or [~n] to the competing rule
2159 | {-# RULES "map Pack" map pack = id #-}

The warning seems to suggests two things:
1. "Class op" -> "dictionary projection" are implemented as rewrite rules and executed the same way as other user-defined RULES
2. These rules run first, and you cannot run anything before them

Now my question is, is 1. actually true? or is that warning just a (white) lie?
If 1. is actually true, would there be any objections to adding a "-1" phase: where RULES specified to start from phase "-1" onward fire before any of the Class op rules.
I'm quite willing to implement the above if A) Class op rules are actually implemented as builtin RULES; B) there a no objections to this "-1" phase.


ghc-devs mailing list
ghc-devs at<mailto:ghc-devs at>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <>

More information about the ghc-devs mailing list