[commit: ghc] master: Document RULES and class methods (889824d)

git at git.haskell.org git at git.haskell.org
Thu Jul 9 11:46:38 UTC 2015


Repository : ssh://git@git.haskell.org/ghc

On branch  : master
Link       : http://ghc.haskell.org/trac/ghc/changeset/889824dd5ea37adc0fbfe851f724ca9331278664/ghc

>---------------------------------------------------------------

commit 889824dd5ea37adc0fbfe851f724ca9331278664
Author: Simon Peyton Jones <simonpj at microsoft.com>
Date:   Thu Jul 9 12:46:58 2015 +0100

    Document RULES and class methods
    
    Relates to Trac #10595


>---------------------------------------------------------------

889824dd5ea37adc0fbfe851f724ca9331278664
 docs/users_guide/glasgow_exts.xml | 55 +++++++++++++++++++++++++++++++++++++++
 1 file changed, 55 insertions(+)

diff --git a/docs/users_guide/glasgow_exts.xml b/docs/users_guide/glasgow_exts.xml
index 6d69c75..1e926a3 100644
--- a/docs/users_guide/glasgow_exts.xml
+++ b/docs/users_guide/glasgow_exts.xml
@@ -12084,6 +12084,61 @@ not going to be inlined before the rule has a chance to fire.
 </para>
 </sect2>
 
+a<sect2 id="rules-class-methods">
+<title>How rules interact with class methods</title>
+
+<para>
+Giving a RULE for a class method is a bad idea:
+<programlisting>
+class C a where
+  op :: a -> a -> a
+
+instance C Bool where
+  op x y = ...rhs for op at Bool...
+
+{-# RULES "f" op True y = False #-}
+</programlisting>
+In this
+example, <literal>op</literal> is not an ordinary top-level function;
+it is a class method.  GHC rapidly rewrites any occurrences of
+<literal>op</literal>-used-at-type-Bool
+to a specialised function, say <literal>opBool</literal>, where
+<programlisting>
+opBool :: Bool -> Bool -> Bool
+opBool x y = ..rhs for op at Bool...
+</programlisting>
+So the RULE never has a chance to fire, for just the same reasons as in <xref linkend="rules-inline"/>.
+</para>
+<para>
+The solution is to define the instance-specific function yourself, with a pragma to prevent
+it being inlined too early, and give a RULE for it:
+<programlisting>
+instance C Bool where
+  op x y = opBool
+
+opBool :: Bool -> Bool -> Bool
+{-# NOINLINE [1] opBool #-}
+opBool x y = ..rhs for op at Bool...
+
+{-# RULES "f" opBool True y = False #-}
+</programlisting>
+If you want a RULE that truly applies to the overloaded class method, the only way to
+do it is like this:
+<programlisting>
+class C a where
+  op_c :: a -> a -> a
+
+op :: C a => a -> a -> a
+{-# NOINLINE [1] op #-}
+op = op_c
+
+{-# RULES "reassociate" op (op x y) z = op x (op y z) #-}
+</programlisting>
+Now the inlining of <literal>op</literal> is delayed until the rule has a chance to fire.
+The down-side is that instance declarations must define <literal>op_c</literal>, but
+all other uses should go via <literal>op</literal>.
+</para>
+</sect2>
 <sect2>
 <title>List fusion</title>
 



More information about the ghc-commits mailing list