<div dir="ltr"><div>Hi Hilco,</div><div><br></div><div>To guarantee no intermediate Vectors are ever allocated, you can use the "Bundle" type in <a href="https://hackage.haskell.org/package/vector-0.12.0.3/docs/Data-Vector-Fusion-Bundle.html">https://hackage.haskell.org/package/vector-0.12.0.3/docs/Data-Vector-Fusion-Bundle.html</a> for intermediate values, and only convert the Bundle to a list or vector in the final step. In fact, most interfaces in the vector package are wrapped with "stream" and "unstream" calls under the hood, using Bundle to do the actual transformation, but still exposing the Vector type as input/output, and the composed stream/unstream calls are eliminated by the ghc rewrite rules.</div><div><br></div>Cheers,<div>Cheng</div></div><br><div class="gmail_quote"><div dir="ltr" class="gmail_attr">On Tue, Sep 17, 2019 at 10:45 AM Hilco Wijbenga <<a href="mailto:hilco.wijbenga@gmail.com">hilco.wijbenga@gmail.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="margin:0px 0px 0px 0.8ex;border-left:1px solid rgb(204,204,204);padding-left:1ex">Hi all,<br>
<br>
I'd like to have a better understanding of fusion and (maybe?) laziness.<br>
<br>
Let's say I have an (exported) type "data EndResult = ... !(Vector<br>
Thing) ..." and an intermediate, unexported type "data<br>
IntermediateResult = ... !(Vector Thing) ...". (I suppose it doesn't<br>
need to be Vector, it could be Set, or some other data structure that<br>
(I imagine) is relatively expensive to map over, unlike, say [].)<br>
<br>
[To start off, I want to state my, possibly incorrect, understanding<br>
of fusion and how it does not (in my expectation) apply to Vector,<br>
Set, et cetera. A List can essentially disappear as it's replaced by a<br>
loop but a Vector would not: the executing code would create and<br>
garbage collect multiple intermediate Vectors before finally returning<br>
the end result.]<br>
<br>
Assume that I need my algorithm to go from initial input to<br>
IntermediateResult to subsequent IntermediateResult (a few times) to<br>
EndResult. In my case, each subsequent IntermediateResult is a bit<br>
smaller than the previous one but that's probably irrelevant.<br>
<br>
Should I prefer IntermediateResult to be lazy? Should I use [] instead<br>
of Vector in the IntermediateResult? What about the functions that<br>
actually operate on IntermediateResult, should I prefer to use [] or<br>
Vector there? I'm currently able to use Data.Vector.concatMap in some<br>
places, is that just as optimized?<br>
<br>
I realize that the correct answer more than likely is "don't worry<br>
about it". And that I'm being very vague. :-) I'm not looking for<br>
anything definitive, I'm just hoping to improve my understanding and<br>
intuition.<br>
<br>
What should I consider when thinking about these types of things? If I<br>
don't want to create two separate implementations and profile them,<br>
are there "obvious" signs one way or another?<br>
<br>
Cheers,<br>
Hilco<br>
_______________________________________________<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-bin/mailman/listinfo/haskell-cafe</a><br>
Only members subscribed via the mailman list are allowed to post.</blockquote></div>