Simon Peyton-Jones wrote:
> Sorry it's taken me a long time to look at this.
> Two things are going on here.
No problem
> module KevinB where
>
> data Arr ix el = Arr Int [(ix,el)] deriving Show
>
> replaceMany :: [(ix,el)] -> Arr ix el -> Arr ix el
> replaceMany = error "In Replace Many"
>
> {-# RULES
> "rule1" forall f,l,a. replaceMany (map f l) a = replaceManyMap f l a
> #-}
>
> replaceManyMap :: (v -> (ix,el)) -> [(ix,el)] -> Arr ix el -> Arr ix el
> replaceManyMap = error "In Replace Many Map"
>
> arr s l = let a = Arr s [] in
> replaceMany l a
>
> If you compile this, replaceMany will be inlined in arr's defn,
> which means that anyone importing KevinB won't see the version
> of arr that has replaceMany in it. So
>
> module KevinA where
> import KevinB
> arr2 s l = arr s (map (\(i,e)->(i+2,e)) l)
>
> will not fire the rule.
>
> Solution: add an INLINE pragma to 'arr'. This has the
> effect of *preventing* inlining in arr's RHS, and causing
> 'arr' to be inlined at every call site.
>
> This is an annoying gotcha when using RULES, but I don't see an
> easy fix.
Whats wrong with simply keeping track of all the functions used in the
LHS of a rule and if one of these functions appears in the RHS of a
definition add an implicate INLINE pragma.
PS: Have you had a chance to look at the rule in my "Generator" post the
the haskell mailing list. The rule is being fired up but the compiler
is not optimizing as well as it could.
--
Kevin Atkinson
[EMAIL PROTECTED]
http://metalab.unc.edu/kevina/