<div dir="ltr">Personally, I disagree with the whole premise. Lists are simple and elegant; you *should* use them most of them time. I'm not saying you should use lists as the data structure for an in-memory database or whatever, but that's the point—most applications only have a handful of data structures that "matter", and lists are great everywhere else.<div><br></div><div>I actually went through and replaced [] with Vector in all of the types we parse from JSON at work, some of which get relatively large. It made the code uglier and didn't meaningfully affect the performance. I undid that change, even though it's exactly the sort of thing this article recommends. In this day and age, simple things *scale*. That's enough most of the time; if you can get away with it you *should*.</div><div><br></div><div>The real advantage of lists comes at an intersection of two points: lists are effective in place of iterators in Haskell and, even misused as data structures, they're *not that bad* most of the time. This means that a good 80% of the time, the advantage of using a type that's compatible with the rest of my code and APIs that use lists "correctly" as iterators easily outweighs any small performance penalty. A list has to get pretty large—or my usage pattern pretty convoluted—before another type is worth the complexity.</div></div><div class="gmail_extra"><br><div class="gmail_quote">On Mon, Mar 13, 2017 at 3:43 AM, Johannes Waldmann <span dir="ltr"><<a href="mailto:johannes.waldmann@htwk-leipzig.de" target="_blank">johannes.waldmann@htwk-leipzig.de</a>></span> wrote:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Hi Olaf -<br>
<span class=""><br>
<br>
> I'd be interested whether there is a way to check<br>
> which of my lists in the source code the compiler managed to "deforest" away.<br>
> Which intermediate files should I look at? What are the tools to inspect?<br>
<br>
</span>Good question, and I don't know an easy answer.<br>
<br>
The general advice is running ghc with "-ddump-simpl"<br>
but I find it quite challenging to scan the output.<br>
<br>
<br>
Here is a simple case where it works:<br>
<br>
$ cat Fuse.hs<br>
<br>
main = print $ sum $ map (^2) [1 .. 1000 :: Int]<br>
<br>
<br>
$ ghc -fforce-recomp -ddump-simpl -O0 Fuse.hs<br>
<br>
no optimisation - shows that "main" calls "map" etc.<br>
<br>
<br>
$ ghc -fforce-recomp -ddump-simpl -O2 Fuse.hs<br>
<br>
fusion works - nice non-allocating inner loop<br>
(lists gone, and Int replaced by Int#)<br>
<br>
Rec {<br>
-- RHS size: {terms: 18, types: 3, coercions: 0}<br>
Main.$wgo [InlPrag=[0], Occ=LoopBreaker]<br>
  :: <a href="http://GHC.Prim.Int#" rel="noreferrer" target="_blank">GHC.Prim.Int#</a> -> <a href="http://GHC.Prim.Int#" rel="noreferrer" target="_blank">GHC.Prim.Int#</a> -> <a href="http://GHC.Prim.Int#" rel="noreferrer" target="_blank">GHC.Prim.Int#</a><br>
[GblId, Arity=2, Caf=NoCafRefs, Str=DmdType <S,1*U><S,U>]<br>
Main.$wgo =<br>
  \ (w_s5kV :: <a href="http://GHC.Prim.Int#" rel="noreferrer" target="_blank">GHC.Prim.Int#</a>) (ww_s5kZ :: <a href="http://GHC.Prim.Int#" rel="noreferrer" target="_blank">GHC.Prim.Int#</a>) -><br>
    case w_s5kV of wild_Xn {<br>
      __DEFAULT -><br>
        Main.$wgo<br>
          (GHC.Prim.+# wild_Xn 1#)<br>
          (GHC.Prim.+# ww_s5kZ (GHC.Prim.*# wild_Xn wild_Xn));<br>
      1000# -> GHC.Prim.+# ww_s5kZ 1000000#<br>
    }<br>
end Rec }<br>
<br>
but the challenge is to find the path from "main" to that,<br>
wading through several other functions that may or may not be related.<br>
<br>
<br>
I can imagine a source annotation like "in the code compiled<br>
from this function  f,  that constructor  C  should never be called"<br>
but this is certainly not easy. Do we really mean "never", or do we mean<br>
"only a bounded number of times" (that is, not in the inner loop).<br>
Perhaps there is no code for  f  itself, because it gets inlined.<br>
<br>
But yes, *some* automated analysis (and human-readable print-out)<br>
of the code after simplification would be nice.<br>
<br>
This could be done as a compiler plug-in?<br>
<a href="https://downloads.haskell.org/~ghc/latest/docs/html/users_guide/extending_ghc.html#compiler-plugins" rel="noreferrer" target="_blank">https://downloads.haskell.org/<wbr>~ghc/latest/docs/html/users_<wbr>guide/extending_ghc.html#<wbr>compiler-plugins</a><br>
<span class="HOEnZb"><font color="#888888"><br>
<br>
- J.<br>
</font></span><div class="HOEnZb"><div class="h5"><br>
<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>