Hello,
<div><br></div><div>I want to use the RULES pragma and cannot get my rules to fire. Here is a simplified example of what I'm trying.</div><div><br></div><div>I define my own version of foldMap for lists:</div><div><div>
<br></div><div> fold :: Monoid m => (a -> m) -> [a] -> m</div><div> fold f = foldr mappend mempty . map f</div><div> -- alternative, trying to avoid interference with foldr/build fusion</div><div> -- fold _ [] = mempty</div>
<div> -- fold f (x:xs) = f x `mappend` fold f xs</div><div> {-# NOINLINE fold #-}</div></div><div><br></div><div>I try using a NOINLINE pragma to make the firing of my rules (which involve fold) more robust. But they don't fire with or without NOINLINE. Also the uncommented version does not make a difference.</div>
<div><br></div><div>I also define a function that creates a singleton list:</div><div><br></div><div><div> single :: a -> [a]</div><div> single x = [x]</div></div><div> {-# NOINLINE single #-}</div><div><br></div>
<div>Now I want to replace calls of `fold f . g single` (or eta-expanded versions of this) by `g f` using the following rules:</div><div><br></div><div><div>{-# RULES</div><div> "monoid fusion pointfree"</div><div>
forall f (g :: forall m . Monoid m => (a -> m) -> b -> m) .</div><div> fold f . g single = g f;</div><div><br></div><div> "monoid fusion pointed, general"</div><div> forall f (g :: forall m . Monoid m => (a -> m) -> b -> m) b .</div>
<div> fold f (g single b) = g f b;</div><div><br></div><div> "monoid fusion pointed, for lists"</div><div> forall f (g :: forall m . Monoid m => (a -> m) -> [a] -> m) xs .</div><div> fold f (g single xs) = g f xs;</div>
<div> #-}</div></div><div><br></div><div>The variations of type signatures (including no signatures at all) for the pattern variables that I tried did not change anything for the better.</div><div><br></div><div>I wrote the third rule only because the second gives a warning that I don't quite understand:</div>
<div><br></div><div><div> Warning: Forall'd type variable b is not bound in RULE lhs</div><div> fold @ m @ a $dMonoid f (g @ [a] $dMonoid (single @ a) b)</div></div><div><div><br></div><div>I try out the rules using the following function that takes the role of `g` in the rules:</div>
<div><br></div><div> idGen :: Monoid m => (a -> m) -> [a] -> m</div><div> idGen _ [] = mempty</div><div> idGen f (x:xs) = f x `mappend` idGen f xs</div><div> {-# NOINLINE idGen #-}</div><div><br>
</div><div>Again, I use NOINLINE just in case that would help the rules fire. Here is a main function where the rules should fire:</div><div><br></div><div> main :: IO ()</div><div> main =</div><div> do print ((fold id . idGen single) [[()]])</div>
<div> print (fold id (idGen single [[()]]))</div></div><div><br></div><div>But they don't.</div><div><br></div><div>Why don't the rules fire, what can I change such that they do, and what to get rid of the warning for the second rule (which I think is the one I should use)?</div>
<div><br></div><div>Best regards,</div><div>Sebastian</div><div><br></div><div>Here is the output of -ddump-simple-stats (once with -fenable-rewrite-rules only and once with -O):</div><div><div><br></div><div># ghc --version</div>
<div>The Glorious Glasgow Haskell Compilation System, version 7.0.1</div></div><div><br></div><div><div># ghc -fenable-rewrite-rules -fforce-recomp -ddump-simpl-stats --make rules</div><div>[1 of 1] Compiling Main ( rules.hs, rules.o )</div>
<div><br></div><div>==================== Grand total simplifier statistics ====================</div><div>Total ticks: 0</div><div><br></div><div>1 SimplifierDone</div><div> 1</div></div><div><br></div><div><div># ghc -O -fforce-recomp -ddump-simpl-stats --make rules</div>
<div>[1 of 1] Compiling Main ( rules.hs, rules.o )</div><div><br></div><div>==================== FloatOut stats: ====================</div><div>0 Lets floated to top level; 0 Lets floated elsewhere; from 4 Lambda groups</div>
<div><br></div><div><br></div><div><br></div><div>==================== FloatOut stats: ====================</div><div>10 Lets floated to top level; 1 Lets floated elsewhere; from 5 Lambda groups</div><div><br></div><div><br>
</div><div><br></div><div>==================== Grand total simplifier statistics ====================</div><div>Total ticks: 144</div><div><br></div><div>34 PreInlineUnconditionally</div><div> 1 eta_Xp5</div><div> 1 g_amr</div>
<div> 1 eta_amx</div><div> 1 k_amJ</div><div> 1 z_amK</div><div> 1 f_amQ</div><div> 1 g_amR</div><div> 1 x_amS</div><div> 1 k_an9</div><div> 1 z_ana</div><div> 1 g_anb</div><div> 1 f_anf</div>
<div> 1 xs_ang</div><div> 1 eta_aoA</div><div> 2 $dShow_aKW</div><div> 2 x_aKX</div><div> 1 ys_aVd</div><div> 1 c_dmm</div><div> 1 n_dmn</div><div> 1 a_snX</div><div> 1 a_so1</div><div> 1 lvl_sod</div>
<div> 1 lvl_soe</div><div> 1 lvl_sof</div><div> 1 lvl_sog</div><div> 1 lvl_soh</div><div> 1 lvl_soi</div><div> 1 lvl_soj</div><div> 1 a_son</div><div> 1 a_sop</div><div> 1 a_sV0</div><div> 1 a_sV2</div>
<div>17 PostInlineUnconditionally</div><div> 1 k_amv</div><div> 1 f_amQ</div><div> 1 g_amR</div><div> 1 c_ani</div><div> 1 n_anj</div><div> 1 m_anI</div><div> 1 k_anJ</div><div> 2 $dShow_aoy</div><div>
2 x_aoz</div><div> 1 c_aVa</div><div> 1 f_aVb</div><div> 1 x_aVc</div><div> 1 a_snV</div><div> 1 a_snZ</div><div> 1 lvl_sVA</div><div>15 UnfoldingDone</div><div> 1 GHC.Base.build</div><div> 1 GHC.Base.foldr</div>
<div> 2 System.IO.print</div><div> 1 GHC.TopHandler.runMainIO</div><div> 2 GHC.Base..</div><div> 1 GHC.Base.mapFB</div><div> 1 GHC.Base.$fMonadIO_$c>></div><div> 2 Main.main</div><div> 2 System.IO.print1</div>
<div> 2 GHC.Show.$fShow[]_$cshow</div><div>8 RuleFired</div><div> 1 Class op >></div><div> 2 Class op show</div><div> 2 Class op showList</div><div> 1 fold/build</div><div> 1 foldr/nil</div><div> 1 map</div>
<div>8 LetFloatFromLet</div><div> 8</div><div>62 BetaReduction</div><div> 1 eta_Xp5</div><div> 1 a_amq</div><div> 1 g_amr</div><div> 1 a_amt</div><div> 1 b_amu</div><div> 1 k_amv</div><div> 1 z_amw</div>
<div> 1 eta_amx</div><div> 1 b_amH</div><div> 1 a_amI</div><div> 1 k_amJ</div><div> 1 z_amK</div><div> 2 b_amN</div><div> 2 c_amO</div><div> 2 a_amP</div><div> 2 f_amQ</div><div> 2 g_amR</div>
<div> 1 x_amS</div><div> 1 a_an7</div><div> 1 b_an8</div><div> 1 k_an9</div><div> 1 z_ana</div><div> 1 g_anb</div><div> 1 a_and</div><div> 1 a1_ane</div><div> 1 f_anf</div><div> 1 xs_ang</div>
<div> 1 b_anh</div><div> 1 c_ani</div><div> 1 n_anj</div><div> 1 a_anG</div><div> 1 b_anH</div><div> 1 m_anI</div><div> 1 k_anJ</div><div> 2 a_aox</div><div> 2 $dShow_aoy</div><div> 2 x_aoz</div>
<div> 1 eta_aoA</div><div> 2 a_aKV</div><div> 2 $dShow_aKW</div><div> 2 x_aKX</div><div> 1 elt_aV7</div><div> 1 lst_aV8</div><div> 1 a_aV9</div><div> 1 c_aVa</div><div> 1 f_aVb</div><div> 1 x_aVc</div>
<div> 1 ys_aVd</div><div> 1 a_dml</div><div> 1 c_dmm</div><div> 1 n_dmn</div><div>13 SimplifierDone</div><div> 13</div></div><div><br></div>