<div dir="ltr">Why not use the state monad transformer?<div><br></div><div><a href="http://hackage.haskell.org/package/transformers-0.5.1.0/docs/Control-Monad-Trans-State-Lazy.html#t:StateT">http://hackage.haskell.org/package/transformers-0.5.1.0/docs/Control-Monad-Trans-State-Lazy.html#t:StateT</a><br></div><div><br></div><div>atomically $ evalStateT todo initialState</div><div><br></div><div>Seems Ok to me</div><div><br></div><div><a name="v:evalStateT" class="" style="margin:0px;padding:0px;font-weight:bold;color:rgb(0,0,0);font-family:monospace;font-size:13px;line-height:16.12px">evalStateT</a><span style="color:rgb(0,0,0);font-family:monospace;font-size:13px;line-height:16.12px;background-color:rgb(240,240,240)"> :: </span><a href="http://hackage.haskell.org/package/base-4.8.1.0/docs/Control-Monad.html#t:Monad" style="margin:0px;padding:0px;text-decoration:none;color:rgb(171,105,84);font-family:monospace;font-size:13px;line-height:16.12px">Monad</a><span style="color:rgb(0,0,0);font-family:monospace;font-size:13px;line-height:16.12px;background-color:rgb(240,240,240)"> m => </span><a href="http://hackage.haskell.org/package/transformers-0.5.1.0/docs/Control-Monad-Trans-State-Lazy.html#t:StateT" style="margin:0px;padding:0px;color:rgb(171,105,84);font-family:monospace;font-size:13px;line-height:16.12px">StateT</a><span style="color:rgb(0,0,0);font-family:monospace;font-size:13px;line-height:16.12px;background-color:rgb(240,240,240)"> s m a -> s -> m a</span><br></div><div><span style="color:rgb(0,0,0);font-family:monospace;font-size:13px;line-height:16.12px;background-color:rgb(240,240,240)"><br></span></div><div><span style="color:rgb(0,0,0);font-family:monospace;font-size:13px;line-height:16.12px;background-color:rgb(240,240,240)">in this case:</span></div><div><span style="color:rgb(0,0,0);font-family:monospace;font-size:13px;line-height:16.12px;background-color:rgb(240,240,240)"><br></span></div><div><a name="v:evalStateT" class="" style="margin:0px;padding:0px;font-weight:bold;color:rgb(0,0,0);font-family:monospace;font-size:13px;line-height:16.12px">evalStateT</a><span style="color:rgb(0,0,0);font-family:monospace;font-size:13px;line-height:16.12px;background-color:rgb(240,240,240)"> ::</span><span style="color:rgb(0,0,0);font-family:monospace;font-size:13px;line-height:16.12px;background-color:rgb(240,240,240)"> </span><a href="http://hackage.haskell.org/package/transformers-0.5.1.0/docs/Control-Monad-Trans-State-Lazy.html#t:StateT" style="margin:0px;padding:0px;color:rgb(171,105,84);font-family:monospace;font-size:13px;line-height:16.12px">StateT</a><span style="color:rgb(0,0,0);font-family:monospace;font-size:13px;line-height:16.12px;background-color:rgb(240,240,240)"> MyState STM a -> MyState -> STM a</span><span style="color:rgb(0,0,0);font-family:monospace;font-size:13px;line-height:16.12px;background-color:rgb(240,240,240)"><br></span></div></div><div class="gmail_extra"><br><div class="gmail_quote">2016-02-09 9:36 GMT+01:00 Jonas Scholl <span dir="ltr"><<a href="mailto:anselm.scholl@tu-harburg.de" target="_blank">anselm.scholl@tu-harburg.de</a>></span>:<br><blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex"><span class="">On 02/09/2016 07:20 AM, Thomas Koster wrote:<br>
> On 9 February 2016 at 14:43, Thomas Koster <<a href="mailto:tkoster@gmail.com">tkoster@gmail.com</a>> wrote:<br>
>> I have an STM transaction that needs some private, temporary state.<br>
>> The most obvious way is to simply pass pure state as arguments, but<br>
>> for efficiency, I would like this state to be some kind of mutable<br>
>> array, like STArray.<br>
<br>
</span>This sounds like optimizing before you know what is really slow,<br>
complicating your code for no good reason...<br>
<span class=""><br>
>><br>
>> I know, STM has TVars and TArray, but since this state is private to<br>
>> the transaction, I am wondering if using TVars/TArrays for private<br>
>> state might be overkill that will unnecessarily slow down the STM<br>
>> commit process. The private state is, by definition, not shared, so<br>
>> including it in the STM log and commit process is, as far as I can<br>
>> tell, pointless.<br>
<br>
</span>The STM log allows you to revert a failed transaction. If you do not<br>
record your writes to an array, you can not revert them and they can<br>
leak outside an aborted transaction.<br>
<span class=""><br>
>><br>
>> ST and STArray still appear to be the most appropriate tools for the<br>
>> private state, because STRefs and STArrays really, really are private.<br>
>><br>
>> So this basically means I want to interleave ST and STM in a "safe"<br>
>> way. That is, if the STM transaction retries, I want the ST state to<br>
>> be vaporised as well.<br>
<br>
</span>So how should this work? Some log recording what you did would be good,<br>
so the runtime knows which changes you did to the array... If you<br>
however create the array in the same transaction, this would work by<br>
just throwing away the whole array.<br>
<span class=""><br>
>><br>
>> Ideally, I would love to be able to say something like this:<br>
>><br>
>> -- | Copy the value from the shared TVar into the private STRef.<br>
>> load :: TVar a -> STRef a -> STSTM s ()<br>
>> load shared private = do<br>
>> value <- liftSTM (readTVar shared)<br>
>> liftST (writeSTRef private value)<br>
>><br>
>> Naturally, that STRef must originate from a call to newSTRef earlier<br>
>> in the same transaction and is private to it, just like the real ST<br>
>> monad. As far as I can tell, I am not trying to weaken either ST or<br>
>> STM in any way here.<br>
>><br>
>> I found the STMonadTrans package on Hackage [1] that claims to<br>
>> implement ST as a monad transformer, STT, which sounds close to what I<br>
>> want. While its documentation does not mention STM, it does say that<br>
>> some monads are unsafe to use as a base monad for STT.<br>
>><br>
>> Is STMonadTrans safe to use with STM?<br>
<br>
</span>It is not even safe to use with Maybe (for now), as it can share<br>
different STRefs and STArrays. I filed a bug report. After the bug is<br>
fixed, I see no reason, why it should not work with STM, as the complete<br>
ST action should be repeated if the STM transaction aborts.<br>
<span class=""><br>
>><br>
>> [1] <a href="https://hackage.haskell.org/package/STMonadTrans" rel="noreferrer" target="_blank">https://hackage.haskell.org/package/STMonadTrans</a><br>
><br>
> On 9 February 2016 at 15:16, Ryan Yates <<a href="mailto:fryguybob@gmail.com">fryguybob@gmail.com</a>> wrote:<br>
>> I also have found need for what I think you are describing but only in the<br>
>> context of transactional arrays where there are multiple fields to<br>
>> initialize while I know that the array is private to the creating thread.<br>
>> For now I'm adding the primitives I need as I go, but I would like to have<br>
>> better safer story. You might be interested in how the stm-containers<br>
>> package uses ST to build internal nodes in transactions [1], [2].<br>
>><br>
>> [1]:<br>
>> <a href="https://github.com/nikita-volkov/stm-containers/blob/master/library/STMContainers/HAMT/Nodes.hs#L36" rel="noreferrer" target="_blank">https://github.com/nikita-volkov/stm-containers/blob/master/library/STMContainers/HAMT/Nodes.hs#L36</a><br>
>> [2]:<br>
>> <a href="https://github.com/nikita-volkov/stm-containers/blob/master/library/STMContainers/WordArray.hs#L118" rel="noreferrer" target="_blank">https://github.com/nikita-volkov/stm-containers/blob/master/library/STMContainers/WordArray.hs#L118</a><br>
><br>
> Thank you Ryan.<br>
><br>
> Indeed, it is by experimenting with stm-containers that the need for<br>
> mixing ST and STM arose. Where the previous iteration of my program<br>
> used plain ST transactions serialized with an MVar, I am experimenting<br>
> with stm-containers with the hope that I will see improved throughput<br>
> for transactions that do not overlap, which, I believe, could complete<br>
> in parallel, at least some of the time.<br>
><br>
> It seems stm-containers itself uses unsafeFreezeArray from the<br>
> "primitive" package. One difference though is that while my private<br>
> array would be thawed, modified and refrozen regularly, the<br>
> stm-containers WordArray stays immutable (not thawed) once frozen, as<br>
> far as I can tell.<br>
<br>
</span>So what happens if you thaw an array, write to it and then abort the<br>
transaction? You have to revert the writes because they could be visible<br>
to the transaction you just aborted. When this transaction restarts, the<br>
array will still contain the values written prior to it. Even if nothing<br>
else contains a reference to it, your array is garbage after you aborted<br>
a transaction only once.<br>
<span class=""><br>
><br>
> Since I am using only a single array for the entire private state,<br>
> sprinkling some runST calls with unsafeThawArray/unsafeFreezeArray in<br>
> my STM transaction may be enough for my needs, as long as I am<br>
> exceptionally careful not to leak one of these arrays into or out of<br>
> any STM transaction demarcated by the "atomically" block. If anybody<br>
> knows of any reason why I should abort this idea, please speak up.<br>
<br>
</span>Keep in mind that ST is only "safe IO" in a sense such that no side<br>
effects are visible to the outside. You lose this if you start to modify<br>
anything which you did not create yourself. I think this is not that<br>
different from using<br>
<a href="http://hackage.haskell.org/package/base-4.8.2.0/docs/GHC-Conc-Sync.html#v:unsafeIOToSTM" rel="noreferrer" target="_blank">http://hackage.haskell.org/package/base-4.8.2.0/docs/GHC-Conc-Sync.html#v:unsafeIOToSTM</a>.<br>
To be safe, you should at least copy the arrays instead of unsafely<br>
thawing them... but then it could be faster just to use TArrays from the<br>
start.<br>
<div class="HOEnZb"><div class="h5"><br>
><br>
> I noticed also that Data.Array.Unsafe in base also has unsafe freezing<br>
> and thawing. Is there a reason to use one over the other?<br>
><br>
> --<br>
> Thomas Koster<br>
> _______________________________________________<br>
> Haskell-Cafe mailing list<br>
> <a href="mailto:Haskell-Cafe@haskell.org">Haskell-Cafe@haskell.org</a><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>
><br>
<br>
<br>
</div></div><br>_______________________________________________<br>
Haskell-Cafe mailing list<br>
<a href="mailto:Haskell-Cafe@haskell.org">Haskell-Cafe@haskell.org</a><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>
<br></blockquote></div><br><br clear="all"><div><br></div>-- <br><div class="gmail_signature">Alberto.</div>
</div>