<div dir="auto">Can you explain how things could go wrong in ST, perhaps with an example? It's hard to see the potential problem.</div><div class="gmail_extra"><br><div class="gmail_quote">On Jun 18, 2017 11:49 PM, "Edward Z. Yang" <<a href="mailto:ezyang@mit.edu">ezyang@mit.edu</a>> wrote:<br type="attribution"><blockquote class="quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">There are two senses of referential transparency here which should be<br>
considered.  First is whether or not you will get the same value results<br>
if you use the compact functionality in ST.  Here, the answer is yes.<br>
Compact normal form has very trivial semantics in this domain, and<br>
it would have been OK even to make compact normal forms be pure<br>
functions.<br>
<br>
Second is whether or not the performance characteristics are preserved.<br>
Here, the situation is different.  Most notably, pure expressions and<br>
invocations of the same runST block may be commoned up (via an<br>
optimization pass like CSE.)  In that case, what was previously two<br>
separate compact blocks may be commoned up into a single one.  This<br>
could be disaster if you were planning to use these blocks as separate<br>
allocation buffers for subsequent modifications.<br>
<br>
This motivated specializing compact to IO.  It won't segfault if you<br>
put it in ST, but the performance characteristics might change.<br>
<br>
Edward<br>
<br>
Excerpts from Andrew Martin's message of 2017-06-18 10:24:09 -0400:<br>
<div class="elided-text">> In the primops file where the compact normal form functions are<br>
> documented (<a href="https://github.com/ghc/ghc/blob/adcd1c62b6d372f100ccf1d5d7cd94f79aaac194/compiler/prelude/primops.txt.pp#L2487" rel="noreferrer" target="_blank">https://github.com/ghc/ghc/<wbr>blob/<wbr>adcd1c62b6d372f100ccf1d5d7cd94<wbr>f79aaac194/compiler/prelude/<wbr>primops.txt.pp#L2487</a>),<br>
> I noticed that all of the functions have type signatures that constrain<br>
> them to only being used in IO. For example:<br>
><br>
>     compactAdd# :: Compact# -> a -> State# RealWorld -> (# State# RealWorld, a #)<br>
><br>
> I would like to know if generalizing these to allow them to work in ST would<br>
> be sound. That is, changing the type signature to:<br>
><br>
>     compactAdd# :: Compact# -> a -> State# s -> (# State# s, a #)<br>
><br>
> I'm not requesting that this change actually be made. I only want to<br>
> know if using unsafeCoerce to create the second function for my own<br>
> project would actually be sound.<br>
><br>
> For those interested in knowing why I want this, it's because there are<br>
> situation where I'm interested in building up a giant structure in a<br>
> compact region, but in a way that doesn't actually require IO. I think<br>
> it's a pity to have to use a type signature with IO and then call<br>
> unsafePerformIO at the end instead of using the more constrained ST,<br>
> and runST, which makes it clear that I'm not doing anything observable<br>
> form the outside.<br>
><br>
> As a minor bonus, the ST version of the Compact data type shouldn't need<br>
> the lock that the IO version does, since concurrent calls to compactAdd<br>
> are not possible.<br>
><br>
> -Andrew Martin<br>
><br>
______________________________<wbr>_________________<br>
Libraries mailing list<br>
<a href="mailto:Libraries@haskell.org">Libraries@haskell.org</a><br>
<a href="http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries" rel="noreferrer" target="_blank">http://mail.haskell.org/cgi-<wbr>bin/mailman/listinfo/libraries</a><br>
</div></blockquote></div><br></div>