diff options
author | Simon Peyton Jones <simonpj@microsoft.com> | 2015-07-09 12:46:58 +0100 |
---|---|---|
committer | Simon Peyton Jones <simonpj@microsoft.com> | 2015-07-09 12:47:19 +0100 |
commit | 889824dd5ea37adc0fbfe851f724ca9331278664 (patch) | |
tree | d3557954e863ee846e85351cbdb3698b9901525b /docs | |
parent | b29633f5cf310824f3e34716e9261162ced779d3 (diff) | |
download | haskell-889824dd5ea37adc0fbfe851f724ca9331278664.tar.gz |
Document RULES and class methods
Relates to Trac #10595
Diffstat (limited to 'docs')
-rw-r--r-- | docs/users_guide/glasgow_exts.xml | 55 |
1 files changed, 55 insertions, 0 deletions
diff --git a/docs/users_guide/glasgow_exts.xml b/docs/users_guide/glasgow_exts.xml index 6d69c75faf..1e926a3113 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> |