<div dir="ltr">I believe it is because of numericEnumFromTo which forces the elements of the list.<div><br></div><div><div class="gmail_extra"><br><div class="gmail_quote">On Wed, Aug 23, 2017 at 10:54 AM, Mateusz Kowalczyk <span dir="ltr"><<a href="mailto:fuuzetsu@fuuzetsu.co.uk" target="_blank">fuuzetsu@fuuzetsu.co.uk</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><div class="HOEnZb"><div class="h5">On 08/23/2017 02:00 PM, Mateusz Kowalczyk wrote:<br>
> Hi,<br>
><br>
> I had few minutes timeout waiting for CI today and I stumbled upon [1].<br>
> This is a many years old question and the optimal solution given there<br>
> was using Vector. I thought that for such a problem it should not be<br>
> necessary at all.<br>
><br>
> Indeed I wrote `mean :: [Int] -> Int` and got a much faster solution.<br>
> However the original signature was `mean :: [Double] -> Int`. After<br>
> trivial changes (change couple of places to Double and add a single<br>
> fromIntegral) I expected the same result: after all, code is nearly<br>
> exactly the same.<br>
><br>
> However to my disappointment, the code in question was much slower than<br>
> the vector solution: how could this be? Looking in Core, I saw that GHC<br>
> was not getting rid of [Double] like it was with [Int]. I was able to<br>
> convince GHC to go back to fusing the list into the worker with a `map<br>
> fromIntegral` but I am unhappy: why is this needed? I don't understand<br>
> why GHC would not decide to fuse the initial attempt. Honestly it seems<br>
> like a bug to me.<br>
><br>
> What are your thoughts? For reference here is the core with<br>
> fromIntegral: as expected, GHC fuses the list and inserts int2Double# as<br>
> it's generating it:<br>
><br>
> ```<br>
> Main.$wgo =<br>
>   \ (w_s5xT :: <a href="http://GHC.Prim.Int#" rel="noreferrer" target="_blank">GHC.Prim.Int#</a>)<br>
>     (ww_s5xX :: <a href="http://GHC.Prim.Int#" rel="noreferrer" target="_blank">GHC.Prim.Int#</a>)<br>
>     (ww1_s5xY :: GHC.Prim.Double#) -><br>
>     case w_s5xT of wild_Xz {<br>
>       __DEFAULT -><br>
>         Main.$wgo<br>
>           (GHC.Prim.+# wild_Xz 1#)<br>
>           (GHC.Prim.+# ww_s5xX 1#)<br>
>           (GHC.Prim.+## ww1_s5xY (GHC.Prim.int2Double# wild_Xz));<br>
>       30000000# -><br>
>         (# GHC.Prim.+# ww_s5xX 1#, GHC.Prim.+## ww1_s5xY 3.0e7## #)<br>
>     }<br>
> ```<br>
><br>
> Contrast this with version that's commented out in [2]:<br>
><br>
> ```<br>
> Main.$wgo =<br>
>   \ (w_s5vE :: [Double])<br>
>     (ww_s5vI :: <a href="http://GHC.Prim.Int#" rel="noreferrer" target="_blank">GHC.Prim.Int#</a>)<br>
>     (ww1_s5vJ :: GHC.Prim.Double#) -><br>
>     case w_s5vE of _ [Occ=Dead] {<br>
>       [] -> (# ww_s5vI, ww1_s5vJ #);<br>
>       : y_a3dU ys_a3dV -><br>
>         case y_a3dU of _ [Occ=Dead] { GHC.Types.D# y1_a3dG -><br>
>         Main.$wgo<br>
>           ys_a3dV (GHC.Prim.+# ww_s5vI 1#) (GHC.Prim.+## ww1_s5vJ y1_a3dG)<br>
>         }<br>
>     }<br>
><br>
> …<br>
><br>
>     case Main.$wgo Main.main3 0# 0.0##<br>
> …<br>
> Main.main3 =<br>
>   GHC.Real.numericEnumFromTo<br>
>     @ Double<br>
>     GHC.Classes.$fOrdDouble<br>
>     GHC.Float.$fFractionalDouble<br>
>     Main.main5<br>
>     Main.main4<br>
> …<br>
> Main.main4 = GHC.Types.D# 3.0e7##<br>
> …<br>
> Main.main5 = GHC.Types.D# 1.0##<br>
> ```<br>
><br>
> Why? There should be nothing stopping it from doing<br>
><br>
> ```<br>
><br>
> Main.$wgo =<br>
>   \ (w_s5xT :: GHC.Prim.Double#)<br>
>     (ww_s5xX :: <a href="http://GHC.Prim.Int#" rel="noreferrer" target="_blank">GHC.Prim.Int#</a>)<br>
>     (ww1_s5xY :: GHC.Prim.Double#) -><br>
>     case w_s5xT of wild_Xz {<br>
>       __DEFAULT -><br>
>         Main.$wgo<br>
>           (GHC.Prim.+# wild_Xz 1#)<br>
>           (GHC.Prim.+# ww_s5xX 1#)<br>
>           (GHC.Prim.+## ww1_s5xY wild_Xz);<br>
>       3.0e7## -><br>
>         (# GHC.Prim.+# ww_s5xX 1#, GHC.Prim.+## ww1_s5xY 3.0e7## #)<br>
> ```<br>
><br>
> Perhaps it's afraid to make the pattern match on a floating point number?<br>
><br>
> Insights welcome.<br>
><br>
><br>
> [1]:<br>
> <a href="https://stackoverflow.com/questions/3300995/computing-the-mean-of-a-list-efficiently-in-haskell/45840148" rel="noreferrer" target="_blank">https://stackoverflow.com/<wbr>questions/3300995/computing-<wbr>the-mean-of-a-list-<wbr>efficiently-in-haskell/<wbr>45840148</a><br>
> [2]: <a href="https://stackoverflow.com/a/45840148/1432740" rel="noreferrer" target="_blank">https://stackoverflow.com/a/<wbr>45840148/1432740</a><br>
><br>
<br>
</div></div>Correction: The signatures of mean I was referring to were supposed to<br>
be ‘[Int] -> Double’ and then ‘[Double] -> Double’. Somewhat obviously.<br>
<div class="HOEnZb"><div class="h5"><br>
--<br>
Mateusz K.<br>
______________________________<wbr>_________________<br>
Haskell-Cafe mailing list<br>
To (un)subscribe, modify options or view archives go to:<br>
<a href="http://mail.haskell.org/cgi-bin/mailman/listinfo/haskell-cafe" rel="noreferrer" target="_blank">http://mail.haskell.org/cgi-<wbr>bin/mailman/listinfo/haskell-<wbr>cafe</a><br>
Only members subscribed via the mailman list are allowed to post.</div></div></blockquote></div><br></div></div></div>