
2011/2/15 Gábor Lehel
This is a semi-related question I've been meaning to ask at some point: I suppose this also means it's not possible to write a class, write some rules for the class, and then have the rules be applied to every instance? (I.e. you'd have to write them separately for each?)
This does work, because it doesn't require the simplifier to lookup up class instances. However, it's a bit fragile. Here is an example: """ class Foo a where foo :: a -> a bar :: a -> a foo_bar :: a -> a {-# RULES "foo/bar" forall x. foo (bar x) = foo_bar x #-} instance Foo Bool where foo = not bar = not foo_bar = not instance Foo Int where foo = (+1) bar x = x - 1 foo_bar = (+2) {-# NOINLINE foo_barish #-} foo_barish :: Foo a => a -> a foo_barish x = foo (bar x) main = do print $ foo (bar False) -- False if rule not applied, True otherwise print $ foo (bar (2 :: Int)) -- 2 if rule not applied, 4, otherwise print $ foo_barish False -- False if rule not applied, True otherwise print $ foo_barish (2 :: Int) -- 2 if rule not applied, 4, otherwise """ With GHC 7, the RULE successfully rewrites the foo.bar composition within foo_barish to use foo_bar. However, it fails to rewrite the two foo.bar compositions inlined directly in main. Thus the output is: """ False 2 True 4 """ The reason it cannot rewrite the calls in main is (I think) because the foo/bar class selectors are inlined before the rule matcher gets to spot them. By using NOINLINE on foo_barish, and ensuring that foo_barish is overloaded, we prevent the simplifier from doing this inlining and hence allow the rule to fire. What is more interesting is that I can't get the foo (bar x) rule to fire on the occurrences within main even if I add NOINLINE pragmas to the foo/bar names in both the class and instance declarations. Personally I would expect writing NOINLINE on the class declaration would prevent the class selector being inlined, allowing the rule to fire, but that is not happening for some reason. Perhaps this is worth a bug report on the GHC trac? It would at least give it a chance of being fixed. Max