<div dir="auto"><div>I also remember using such rules in my code. See for example:</div><div dir="auto"><br></div><div dir="auto"><a href="https://github.com/basvandijk/aeson/blob/json-builder/Data/Aeson/Types/Internal.hs#L273">https://github.com/basvandijk/aeson/blob/json-builder/Data/Aeson/Types/Internal.hs#L273</a></div><div dir="auto"><br></div><div dir="auto">TIL rules like that are fragile.</div><div dir="auto"><br></div><div dir="auto">Bas</div><div dir="auto"><div class="gmail_extra" dir="auto"><br><div class="gmail_quote">Op 17 feb. 2017 3:49 p.m. schreef "David Feuer" <<a href="mailto:david@well-typed.com">david@well-typed.com</a>>:<br type="attribution"><blockquote class="quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">I've never used such rules myself, but when I asked Duncan Coutts about<br>
whether and how such rules were used in the wild, he said<br>
<br>
> Well I've certainly tried to use that in the past.<br>
> A previous version of the cbor lib which used a different<br>
> representation did a lot of matching on constructors to re-arrange input to<br>
> an interpreter, until I discovered that GHC<br>
> actually uses constructor wrappers and that matching on constructors was<br>
> thus not reliable .<br>
<br>
He described such rules as "a totally legit thing to want to do". If a<br>
datatype represents an AST, then rewriting its terms can optimize the<br>
constructed programs. Of course, it's ultimately up to you. I have no dog in<br>
this race myself; my concern was for other people's code that could break as a<br>
result. Certainly such code is already fragile when strict constructors are<br>
involved, but if people have cleverly figured out that lazy constructors are<br>
more reliable in that regard, they could be using it. I don't know.<br>
<br>
David<br>
<br>
On Friday, February 17, 2017 8:06:17 AM EST Simon Peyton Jones via ghc-devs<br>
wrote:<br>
<div class="elided-text">> {-# RULES   "L" LCon1 0 = LCon2<br>
> Oh I missed this entirely. You want to write a rule FOR a data<br>
> constructor????   I thought you just meant one that matches on a data<br>
> constructor.<br>
 That is you want (L 0) to rewrite, all by itself, to LCon2?<br>
> That had never occurred to me as a possibility.  Bizarre. Let’s not do<br>
> that.<br>
><br>
> ·         GHC does not (knowingly) support it today<br>
><br>
> ·         It is a deeply weird thing to do<br>
><br>
> ·         If you want to do it, write you own “smart constructor” mkLCon1,<br>
> that inlines when you say<br>
<br>
> mkLCon1 x = LCon1 x<br>
><br>
> {-# INILNE [0] mkLCon1 #-}<br>
><br>
> {-# RULES “L” mkLCon1 x = LCon2 #-}<br>
><br>
><br>
> Problem solved.<br>
> Simon<br>
><br>
> From: David Feuer [mailto:<a href="mailto:david.feuer@gmail.com">david.feuer@gmail.com</a>]<br>
> Sent: 17 February 2017 00:30<br>
> To: Simon Peyton Jones <<a href="mailto:simonpj@microsoft.com">simonpj@microsoft.com</a>><br>
> Cc: ghc-devs <<a href="mailto:ghc-devs@haskell.org">ghc-devs@haskell.org</a>>; Reid Barton <<a href="mailto:rwbarton@gmail.com">rwbarton@gmail.com</a>>; Ben<br>
> Gamari <<a href="mailto:bgamari@gmail.com">bgamari@gmail.com</a>><br>
 Subject: RE: Static data and RULES<br>
><br>
> Let me give an example. Suppose we have<br>
><br>
> data L = LCon1 Int | LCon2<br>
> data S = SCon !Int<br>
><br>
> {-# RULES<br>
> "L" LCon1 0 = LCon2<br>
> "S" forall x . f (SCon x) = g x<br>
>  #-}<br>
><br>
> The immediate problem today is with "S". The SCon wrapper could very well<br>
> inline before the rule has a chance to fire. We'd like to be able to phase<br>
> that inline to give it a chance.<br>
<br>
> The "L" rule becomes problematic when we try to identify static data the<br>
> simplifier shouldn't have to try to optimize. If it identifies LCon 0 as<br>
> static, the "L" rule will never fire.<br>
<br>
> On Feb 16, 2017 7:08 PM, "David Feuer"<br>
</div><div class="quoted-text">> <<a href="mailto:david.feuer@gmail.com">david.feuer@gmail.com</a><mailto:<a href="mailto:david.feuer@gmail.com"><wbr>david.feuer@gmail.com</a>>> wrote:<br>
 Semantically,<br>
> the proposed scheme is very nearly equivalent to breaking *every* data<br>
> constructor into a worker and a wrapper, and allowing INLINE and NOINLINE<br>
> pragmas on the wrappers. That would allow terms built only from constructor<br>
> workers and literals to be identified as they're constructed in any stage<br>
> and left alone by the simplifier. It would also allow people using RULES<br>
> that match on constructors to make those work reliably, by making sure the<br>
> bindings they match on don't inline away or get marked static too early. Of<br>
> course, we don't actually need to add more worker/wrapper pairs to do this;<br>
> we can fake that.<br>
> On Feb 16, 2017 6:53 PM, "Simon Peyton Jones"<br>
</div><div class="quoted-text">> <<a href="mailto:simonpj@microsoft.com">simonpj@microsoft.com</a><mailto:<a href="mailto:simonpj@microsoft.com"><wbr>simonpj@microsoft.com</a>>> wrote:<br>
 I’m sorry I<br>
> still don’t understand the problem.  Can you give an example?  It all works<br>
> fine today; what will change in the proposed new scheme.  Indeed what IS<br>
> the proposed new scheme?<br>
> I’m lost<br>
><br>
> Simon<br>
><br>
> From: David Feuer<br>
</div>> [mailto:<a href="mailto:david.feuer@gmail.com">david.feuer@gmail.com</a><<wbr>mailto:<a href="mailto:david.feuer@gmail.com">david.feuer@gmail.com</a>>]<br>
<div class="quoted-text"> Sent: 16<br>
> February 2017 23:51<br>
> To: Simon Peyton Jones<br>
</div>> <<a href="mailto:simonpj@microsoft.com">simonpj@microsoft.com</a><mailto:<a href="mailto:simonpj@microsoft.com"><wbr>simonpj@microsoft.com</a>>><br>
 Cc: ghc-devs<br>
> <<a href="mailto:ghc-devs@haskell.org">ghc-devs@haskell.org</a><mailto:<a href="mailto:ghc-devs@haskell.org">g<wbr>hc-devs@haskell.org</a>>>; Reid Barton<br>
> <<a href="mailto:rwbarton@gmail.com">rwbarton@gmail.com</a><mailto:<a href="mailto:rwbarton@gmail.com">rwb<wbr>arton@gmail.com</a>>>; Ben Gamari<br>
> <<a href="mailto:bgamari@gmail.com">bgamari@gmail.com</a><mailto:<a href="mailto:bgamari@gmail.com">bgam<wbr>ari@gmail.com</a>>> Subject: RE: Static data and<br>
<div class="quoted-text">> RULES<br>
><br>
> Sorry; guess I should have given more background on that. This goes back to<br>
> the performance problems Ben encountered in Typeable. The goal is to avoid<br>
> trying to optimize something over and over that's never ever going to<br>
> change. If we know that a term is made only of static data, we can skip it<br>
> altogether in simplification. Suppose we have<br>
<br>
> foo = Just (Right [1])<br>
><br>
> Then no amount of optimization will ever be useful. But what about RULES? If<br>
> the outermost pattern in a rule matches on a data constructor, then it's<br>
> not static anymore! We may be replacing it with something else. So we need<br>
> a finer mechanism. We *also* need a finer mechanism for strict constructors<br>
> in general. We need to avoid inlining those too early if they're mentioned<br>
> in any position in RULES. Trying to make this work right automagically<br>
> looks a bit tricky in the face of orphan rules and such.<br>
<br>
> On Feb 16, 2017 6:35 PM, "Simon Peyton Jones"<br>
</div><div class="quoted-text">> <<a href="mailto:simonpj@microsoft.com">simonpj@microsoft.com</a><mailto:<a href="mailto:simonpj@microsoft.com"><wbr>simonpj@microsoft.com</a>>> wrote:<br>
 I don’t<br>
> understand any of this.<br>
><br>
> However, RULES are allowed to match on data constructors and it would be<br>
> nice to let that keep happening.<br>
<br>
> Why won’t it keep happening?  What is the problem you are trying to solve?<br>
> Why does the fast-path make it harder?<br>
<br>
> Maybe open a ticket?<br>
><br>
> Simon<br>
><br>
> From: ghc-devs<br>
</div>> [mailto:<a href="mailto:ghc-devs-bounces@haskell.org">ghc-devs-bounces@<wbr>haskell.org</a><mailto:<a href="mailto:ghc-devs-bounces@haskell.org">ghc-devs-<wbr>bounces@haskell.org</a>>]<br>
<div class="quoted-text">> On Behalf Of David Feuer<br>
 Sent: 16 February 2017 22:13<br>
</div>> To: Ben Gamari <<a href="mailto:bgamari@gmail.com">bgamari@gmail.com</a><mailto:<a href="mailto:bgamari@gmail.com">bgam<wbr>ari@gmail.com</a>>>; Reid Barton<br>
> <<a href="mailto:rwbarton@gmail.com">rwbarton@gmail.com</a><mailto:<a href="mailto:rwbarton@gmail.com">rwb<wbr>arton@gmail.com</a>>><br>
 Cc: ghc-devs<br>
> <<a href="mailto:ghc-devs@haskell.org">ghc-devs@haskell.org</a><mailto:<a href="mailto:ghc-devs@haskell.org">g<wbr>hc-devs@haskell.org</a>>><br>
<div class="elided-text">> Subject: Static data and RULES<br>
><br>
> Ben Gamari and Reid Barton are interested in making it cheaper for static<br>
> data to pass through simplification. The basic idea is that if a term is<br>
> already made entirely of data constructors and literals, then there's<br>
> nothing left to optimize.<br>
<br>
> However, RULES are allowed to match on data constructors and it would be<br>
> nice to let that keep happening. But on the other hand, RULES are<br>
> apparently (according to Duncan Coutts) already broken for strict data<br>
> constructors, because they have workers and wrappers.<br>
<br>
> My thought: let's allow phased INLINE and NOINLINE pragmas for data<br>
> constructors. The default would be INLINE. The ~ phase choice would not be<br>
> available: once inline, always inline.<br>
<br>
> Semantics<br>
> ~~~~~~~~~~<br>
><br>
> For all constructors:<br>
><br>
> If a constructor is allowed by pragmas to inline in a certain phase, then in<br>
> that phase terms built from it can be considered static. Once static,<br>
> always static.<br>
<br>
> If a constructor is not allowed to inline in a certain phase, terms built<br>
> from it will be considered non-static.<br>
<br>
> After demand analysis and worker/wrapper, all constructors are considered<br>
> inline.<br>
<br>
> For strict constructors:<br>
><br>
> A strict constructor wrapper prohibited from inlining in a certain phase<br>
> simply will not.<br>
<br>
> Strict constructor wrappers will all be allowed to inline after demand<br>
> analysis and worker/wrapper. This matches the way we now handle wrappers<br>
> actually created in that phase.<br>
<br>
> Syntax:<br>
><br>
> For GADT syntax, this is easy:<br>
><br>
> data Foo ... where<br>
>   {-# INLINE [1] Bar #-}<br>
>   Bar :: ...<br>
><br>
> For traditional syntax, I think it's probably best to pull the pragmas to<br>
> the top:<br>
<br>
> {-# NOINLINE Quux #-}<br>
> data Baz ... = Quux ... | ...<br>
<br>
</div><div class="elided-text">______________________________<wbr>_________________<br>
ghc-devs mailing list<br>
<a href="mailto:ghc-devs@haskell.org">ghc-devs@haskell.org</a><br>
<a href="http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs" rel="noreferrer" target="_blank">http://mail.haskell.org/cgi-<wbr>bin/mailman/listinfo/ghc-devs</a><br>
</div></blockquote></div><br></div></div></div>