<html><head><meta http-equiv="Content-Type" content="text/html; charset=us-ascii"></head><body style="word-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;" class="">Oh, a bugfix: the new tail reference should be returned after update, so a thread local stream reference can technically be cached.<div class=""><br class=""></div><div class="">And I realize this is more than you originally need, never mind if it's not so useful to you.<br class=""><div class=""><br class=""></div><div class=""><div style="color: rgb(212, 190, 152); background-color: rgb(23, 24, 24); font-family: Menlo, Monaco, "Courier New", monospace; line-height: 18px; white-space: pre;" class=""><br class=""><div class=""><span style="color: #cc524b;" class="">data</span><span style="color: #d4bfa0;" class=""> </span><span style="color: #6b95c5;" class="">ValueNode</span><span style="color: #d4bfa0;" class=""> </span><span style="color: #82aed8;" class="">a</span><span style="color: #d4bfa0;" class=""> </span><span style="color: #cc524b;font-weight: bold;" class="">=</span><span style="color: #d4bfa0;" class=""> </span><span style="color: #cca143;" class="">ValueNode</span></div><div class=""><span style="color: #d4bfa0;" class=""> </span><span style="color: #cca143;" class="">{</span><span style="color: #d4bfa0;" class=""> </span><span style="color: #cca143;" class="">node'value</span><span style="color: #d4bfa0;" class=""> </span><span style="color: #cc524b;font-weight: bold;" class="">::</span><span style="color: #d4bfa0;" class=""> </span><span style="color: #82aed8;" class="">a</span>,</div><div class=""><span style="color: #d4bfa0;" class=""> </span><span style="color: #cca143;" class="">node'timestamp</span><span style="color: #d4bfa0;" class=""> </span><span style="color: #cc524b;font-weight: bold;" class="">::</span><span style="color: #d4bfa0;" class=""> </span><span style="color: #6b95c5;" class="">Timestamp</span>,</div><div class=""><span style="color: #d4bfa0;" class=""> </span><span style="color: #cca143;" class="">node'next</span><span style="color: #d4bfa0;" class=""> </span><span style="color: #cc524b;font-weight: bold;" class="">::</span><span style="color: #d4bfa0;" class=""> </span><span style="color: #6b95c5;" class="">ValueSink</span><span style="color: #d4bfa0;" class=""> </span><span style="color: #82aed8;" class="">a</span></div><div class=""><span style="color: #d4bfa0;" class=""> </span><span style="color: #cca143;" class="">}</span></div><br class=""><div class=""><span style="color: #cc524b;" class="">type</span><span style="color: #d4bfa0;" class=""> </span><span style="color: #6b95c5;" class="">ValueSink</span><span style="color: #d4bfa0;" class=""> </span><span style="color: #82aed8;" class="">a</span><span style="color: #d4bfa0;" class=""> </span><span style="color: #cc524b;font-weight: bold;" class="">=</span><span style="color: #d4bfa0;" class=""> </span><span style="color: #6b95c5;" class="">TMVar</span><span style="color: #d4bfa0;" class=""> </span>(<span style="color: #6b95c5;" class="">ValueNode</span><span style="color: #d4bfa0;" class=""> </span><span style="color: #82aed8;" class="">a</span>)</div><br class=""><div class=""><span style="color: #cc524b;" class="">type</span><span style="color: #d4bfa0;" class=""> </span><span style="color: #6b95c5;" class="">Timestamp</span><span style="color: #d4bfa0;" class=""> </span><span style="color: #cc524b;font-weight: bold;" class="">=</span><span style="color: #d4bfa0;" class=""> </span><span style="color: #6b95c5;" class="">Int</span></div><br class=""><div class=""><span style="color: #66a89d;" class="">seekTail</span><span style="color: #96b946;" class=""> </span><span style="color: #cc524b;font-weight: bold;" class="">::</span></div><div class=""><span style="color: #96b946;" class=""> </span><span style="color: #cc524b;font-style: italic;" class="">forall</span><span style="color: #96b946;" class=""> </span><span style="color: #82aed8;" class="">a</span><span style="color: #cc524b;font-weight: bold;" class="">.</span></div><div class=""><span style="color: #96b946;" class=""> </span>(<span style="color: #82aed8;" class="">a</span><span style="color: #96b946;" class=""> </span><span style="color: #cc524b;font-weight: bold;" class="">-></span><span style="color: #96b946;" class=""> </span><span style="color: #6b95c5;" class="">Timestamp</span><span style="color: #96b946;" class=""> </span><span style="color: #cc524b;font-weight: bold;" class="">-></span><span style="color: #96b946;" class=""> </span><span style="color: #82aed8;" class="">a</span><span style="color: #96b946;" class=""> </span><span style="color: #cc524b;font-weight: bold;" class="">-></span><span style="color: #96b946;" class=""> </span><span style="color: #6b95c5;" class="">Timestamp</span><span style="color: #96b946;" class=""> </span><span style="color: #cc524b;font-weight: bold;" class="">-></span><span style="color: #96b946;" class=""> </span><span style="color: #82aed8;" class="">a</span>)<span style="color: #96b946;" class=""> </span><span style="color: #cc524b;font-weight: bold;" class="">-></span></div><div class=""><span style="color: #96b946;" class=""> </span><span style="color: #6b95c5;" class="">ValueSink</span><span style="color: #96b946;" class=""> </span><span style="color: #82aed8;" class="">a</span><span style="color: #96b946;" class=""> </span><span style="color: #cc524b;font-weight: bold;" class="">-></span></div><div class=""><span style="color: #96b946;" class=""> </span><span style="color: #6b95c5;" class="">STM</span><span style="color: #96b946;" class=""> </span>(<span style="color: #6b95c5;" class="">ValueSink</span><span style="color: #96b946;" class=""> </span><span style="color: #82aed8;" class="">a</span>,<span style="color: #96b946;" class=""> </span><span style="color: #6b95c5;" class="">Maybe</span><span style="color: #96b946;" class=""> </span>(<span style="color: #6b95c5;" class="">ValueNode</span><span style="color: #96b946;" class=""> </span><span style="color: #82aed8;" class="">a</span>))</div><div class=""><span style="color: #d4bfa0;" class="">seekTail f sink </span><span style="color: #cc524b;font-weight: bold;" class="">=</span><span style="color: #d4bfa0;" class=""> go sink </span><span style="color: #cca143;" class="">Nothing</span></div><div class=""><span style="color: #d4bfa0;" class=""> </span><span style="color: #cc524b;" class="">where</span></div><div class=""><span style="color: #96b946;" class=""> </span><span style="color: #66a89d;" class="">go</span><span style="color: #96b946;" class=""> </span><span style="color: #cc524b;font-weight: bold;" class="">::</span></div><div class=""><span style="color: #96b946;" class=""> </span><span style="color: #6b95c5;" class="">ValueSink</span><span style="color: #96b946;" class=""> </span><span style="color: #82aed8;" class="">a</span><span style="color: #96b946;" class=""> </span><span style="color: #cc524b;font-weight: bold;" class="">-></span></div><div class=""><span style="color: #96b946;" class=""> </span><span style="color: #6b95c5;" class="">Maybe</span><span style="color: #96b946;" class=""> </span>(<span style="color: #6b95c5;" class="">ValueNode</span><span style="color: #96b946;" class=""> </span><span style="color: #82aed8;" class="">a</span>)<span style="color: #96b946;" class=""> </span><span style="color: #cc524b;font-weight: bold;" class="">-></span></div><div class=""><span style="color: #96b946;" class=""> </span><span style="color: #6b95c5;" class="">STM</span><span style="color: #96b946;" class=""> </span>(<span style="color: #6b95c5;" class="">ValueSink</span><span style="color: #96b946;" class=""> </span><span style="color: #82aed8;" class="">a</span>,<span style="color: #96b946;" class=""> </span><span style="color: #6b95c5;" class="">Maybe</span><span style="color: #96b946;" class=""> </span>(<span style="color: #6b95c5;" class="">ValueNode</span><span style="color: #96b946;" class=""> </span><span style="color: #82aed8;" class="">a</span>))</div><div class=""><span style="color: #d4bfa0;" class=""> go ref prevNode </span><span style="color: #cc524b;font-weight: bold;" class="">=</span></div><div class=""><span style="color: #d4bfa0;" class=""> tryReadTMVar ref </span><span style="color: #a3d349;" class="">>>=</span><span style="color: #d4bfa0;" class=""> </span><span style="color: #cc524b;font-weight: bold;" class="">\</span><span style="color: #cc524b;" class="">case</span></div><div class=""><span style="color: #d4bfa0;" class=""> </span><span style="color: #cca143;" class="">Nothing</span><span style="color: #d4bfa0;" class=""> </span><span style="color: #cc524b;font-weight: bold;" class="">-></span><span style="color: #d4bfa0;" class=""> return </span>(<span style="color: #d4bfa0;" class="">ref</span>,<span style="color: #d4bfa0;" class=""> prevNode</span>)</div><div class=""><span style="color: #d4bfa0;" class=""> </span><span style="color: #cca143;" class="">Just</span><span style="color: #d4bfa0;" class=""> self</span><span style="color: #cca143;" class="">@</span>(<span style="color: #cca143;" class="">ValueNode</span><span style="color: #d4bfa0;" class=""> spotVal spotTs nxt</span>)<span style="color: #d4bfa0;" class=""> </span><span style="color: #cc524b;font-weight: bold;" class="">-></span></div><div class=""><span style="color: #d4bfa0;" class=""> go nxt </span><span style="color: #a3d349;" class="">$</span></div><div class=""><span style="color: #d4bfa0;" class=""> </span><span style="color: #cca143;" class="">Just</span></div><div class=""><span style="color: #d4bfa0;" class=""> self</span></div><div class=""><span style="color: #d4bfa0;" class=""> </span><span style="color: #cca143;" class="">{</span><span style="color: #d4bfa0;" class=""> </span><span style="color: #cca143;" class="">node'value</span><span style="color: #d4bfa0;" class=""> </span><span style="color: #cc524b;font-weight: bold;" class="">=</span><span style="color: #d4bfa0;" class=""> </span><span style="color: #cc524b;" class="">case</span><span style="color: #d4bfa0;" class=""> prevNode </span><span style="color: #cc524b;" class="">of</span></div><div class=""><span style="color: #d4bfa0;" class=""> </span><span style="color: #cca143;" class="">Nothing</span><span style="color: #d4bfa0;" class=""> </span><span style="color: #cc524b;font-weight: bold;" class="">-></span><span style="color: #d4bfa0;" class=""> spotVal</span></div><div class=""><span style="color: #d4bfa0;" class=""> </span><span style="color: #cca143;" class="">Just</span><span style="color: #d4bfa0;" class=""> </span>(<span style="color: #cca143;" class="">ValueNode</span><span style="color: #d4bfa0;" class=""> prevVal prevTs _prevNxt</span>)<span style="color: #d4bfa0;" class=""> </span><span style="color: #cc524b;font-weight: bold;" class="">-></span></div><div class=""><span style="color: #d4bfa0;" class=""> f prevVal prevTs spotVal spotTs</span></div><div class=""><span style="color: #d4bfa0;" class=""> </span><span style="color: #cca143;" class="">}</span></div><br class=""><div class=""><span style="color: #66a89d;" class="">updateValue</span><span style="color: #96b946;" class=""> </span><span style="color: #cc524b;font-weight: bold;" class="">::</span></div><div class=""><span style="color: #96b946;" class=""> </span><span style="color: #cc524b;font-style: italic;" class="">forall</span><span style="color: #96b946;" class=""> </span><span style="color: #82aed8;" class="">a</span><span style="color: #96b946;" class=""> </span><span style="color: #82aed8;" class="">m</span><span style="color: #cc524b;font-weight: bold;" class="">.</span></div><div class=""><span style="color: #96b946;" class=""> </span><span style="color: #6b95c5;" class="">MonadIO</span><span style="color: #96b946;" class=""> </span><span style="color: #82aed8;" class="">m</span><span style="color: #96b946;" class=""> </span><span style="color: #cc524b;font-weight: bold;" class="">=></span></div><div class=""><span style="color: #96b946;" class=""> </span>(<span style="color: #6b95c5;" class="">Maybe</span><span style="color: #96b946;" class=""> </span>(<span style="color: #82aed8;" class="">a</span>,<span style="color: #96b946;" class=""> </span><span style="color: #6b95c5;" class="">Timestamp</span>)<span style="color: #96b946;" class=""> </span><span style="color: #cc524b;font-weight: bold;" class="">-></span><span style="color: #96b946;" class=""> </span><span style="color: #82aed8;" class="">m</span><span style="color: #96b946;" class=""> </span>(<span style="color: #82aed8;" class="">a</span>,<span style="color: #96b946;" class=""> </span><span style="color: #6b95c5;" class="">Timestamp</span>))<span style="color: #96b946;" class=""> </span><span style="color: #cc524b;font-weight: bold;" class="">-></span></div><div class=""><span style="color: #96b946;" class=""> </span><span style="color: #6b95c5;" class="">ValueSink</span><span style="color: #96b946;" class=""> </span><span style="color: #82aed8;" class="">a</span><span style="color: #96b946;" class=""> </span><span style="color: #cc524b;font-weight: bold;" class="">-></span></div><div class=""><span style="color: #96b946;" class=""> </span><span style="color: #82aed8;" class="">m</span><span style="color: #96b946;" class=""> </span>(<span style="color: #6b95c5;" class="">ValueSink</span><span style="color: #96b946;" class=""> </span><span style="color: #82aed8;" class="">a</span>)</div><div class=""><span style="color: #d4bfa0;" class="">updateValue f sink </span><span style="color: #cc524b;font-weight: bold;" class="">=</span><span style="color: #d4bfa0;" class=""> </span><span style="color: #cc524b;" class="">do</span></div><div class=""><span style="color: #d4bfa0;" class=""> </span>(<span style="color: #d4bfa0;" class="">tailRef</span>,<span style="color: #d4bfa0;" class=""> tailNode</span>)<span style="color: #d4bfa0;" class=""> </span><span style="color: #cc524b;font-weight: bold;" class=""><-</span><span style="color: #d4bfa0;" class=""> liftIO </span><span style="color: #a3d349;" class="">$</span><span style="color: #d4bfa0;" class=""> atomically </span><span style="color: #a3d349;" class="">$</span><span style="color: #d4bfa0;" class=""> seekTail justLatest sink</span></div><div class=""><span style="color: #d4bfa0;" class=""> </span><span style="color: #cc524b;" class="">case</span><span style="color: #d4bfa0;" class=""> tailNode </span><span style="color: #cc524b;" class="">of</span></div><div class=""><span style="color: #d4bfa0;" class=""> </span><span style="color: #cca143;" class="">Nothing</span><span style="color: #d4bfa0;" class=""> </span><span style="color: #cc524b;font-weight: bold;" class="">-></span><span style="color: #d4bfa0;" class=""> </span><span style="color: #cc524b;" class="">do</span></div><div class=""><span style="color: #d4bfa0;" class=""> </span>(<span style="color: #d4bfa0;" class="">myVal</span>,<span style="color: #d4bfa0;" class=""> myTs</span>)<span style="color: #d4bfa0;" class=""> </span><span style="color: #cc524b;font-weight: bold;" class=""><-</span><span style="color: #d4bfa0;" class=""> f </span><span style="color: #cca143;" class="">Nothing</span></div><div class=""><span style="color: #d4bfa0;" class=""> liftIO </span><span style="color: #a3d349;" class="">$</span></div><div class=""><span style="color: #d4bfa0;" class=""> atomically </span><span style="color: #a3d349;" class="">$</span><span style="color: #d4bfa0;" class=""> </span><span style="color: #cc524b;" class="">do</span></div><div class=""><span style="color: #d4bfa0;" class=""> nxt </span><span style="color: #cc524b;font-weight: bold;" class=""><-</span><span style="color: #d4bfa0;" class=""> newEmptyTMVar</span></div><div class=""><span style="color: #d4bfa0;" class=""> void </span><span style="color: #a3d349;" class="">$</span><span style="color: #d4bfa0;" class=""> tryPutTMVar tailRef </span><span style="color: #a3d349;" class="">$</span><span style="color: #d4bfa0;" class=""> </span><span style="color: #cca143;" class="">ValueNode</span><span style="color: #d4bfa0;" class=""> myVal myTs nxt</span></div><div class=""><span style="color: #d4bfa0;" class=""> return nxt</span></div><div class=""><span style="color: #d4bfa0;" class=""> </span><span style="color: #cca143;" class="">Just</span><span style="color: #d4bfa0;" class=""> </span>(<span style="color: #cca143;" class="">ValueNode</span><span style="color: #d4bfa0;" class=""> spotVal spotTs spotNxt</span>)<span style="color: #d4bfa0;" class=""> </span><span style="color: #cc524b;font-weight: bold;" class="">-></span><span style="color: #d4bfa0;" class=""> </span><span style="color: #cc524b;" class="">do</span></div><div class=""><span style="color: #d4bfa0;" class=""> </span>(<span style="color: #d4bfa0;" class="">myVal</span>,<span style="color: #d4bfa0;" class=""> myTs</span>)<span style="color: #d4bfa0;" class=""> </span><span style="color: #cc524b;font-weight: bold;" class=""><-</span><span style="color: #d4bfa0;" class=""> f </span><span style="color: #a3d349;" class="">$</span><span style="color: #d4bfa0;" class=""> </span><span style="color: #cca143;" class="">Just</span><span style="color: #d4bfa0;" class=""> </span>(<span style="color: #d4bfa0;" class="">spotVal</span>,<span style="color: #d4bfa0;" class=""> spotTs</span>)</div><div class=""><span style="color: #d4bfa0;" class=""> newNxt </span><span style="color: #cc524b;font-weight: bold;" class=""><-</span><span style="color: #d4bfa0;" class=""> liftIO newEmptyTMVarIO</span></div><div class=""><span style="color: #d4bfa0;" class=""> </span><span style="color: #cc524b;" class="">let</span><span style="color: #d4bfa0;" class=""> newTail </span><span style="color: #cc524b;font-weight: bold;" class="">=</span><span style="color: #d4bfa0;" class=""> </span><span style="color: #cca143;" class="">ValueNode</span><span style="color: #d4bfa0;" class=""> myVal myTs newNxt</span></div><br class=""><div class=""><span style="color: #96b946;" class=""> </span><span style="color: #66a89d;" class="">putAsNewTailOrDiscard</span><span style="color: #96b946;" class=""> </span><span style="color: #cc524b;font-weight: bold;" class="">::</span><span style="color: #96b946;" class=""> </span><span style="color: #6b95c5;" class="">ValueSink</span><span style="color: #96b946;" class=""> </span><span style="color: #82aed8;" class="">a</span><span style="color: #96b946;" class=""> </span><span style="color: #cc524b;font-weight: bold;" class="">-></span><span style="color: #96b946;" class=""> </span><span style="color: #6b95c5;" class="">STM</span><span style="color: #96b946;" class=""> </span>()</div><div class=""><span style="color: #d4bfa0;" class=""> putAsNewTailOrDiscard nodeRef </span><span style="color: #cc524b;font-weight: bold;" class="">=</span></div><div class=""><span style="color: #d4bfa0;" class=""> putTMVar nodeRef newTail </span><span style="color: #96b946;font-weight: bold;" class="">`</span><span style="color: #96b946;" class="">orElse</span><span style="color: #96b946;font-weight: bold;" class="">`</span><span style="color: #d4bfa0;" class=""> yetOther'sTail</span></div><div class=""><span style="color: #d4bfa0;" class=""> </span><span style="color: #cc524b;" class="">where</span></div><div class=""><span style="color: #d4bfa0;" class=""> yetOther'sTail </span><span style="color: #cc524b;font-weight: bold;" class="">=</span><span style="color: #d4bfa0;" class=""> </span><span style="color: #cc524b;" class="">do</span></div><div class=""><span style="color: #d4bfa0;" class=""> </span>(<span style="color: #cca143;" class="">ValueNode</span><span style="color: #d4bfa0;" class=""> _other'sVal other'sTs other'sNxt</span>)<span style="color: #d4bfa0;" class=""> </span><span style="color: #cc524b;font-weight: bold;" class=""><-</span></div><div class=""><span style="color: #d4bfa0;" class=""> readTMVar nodeRef</span></div><div class=""><span style="color: #d4bfa0;" class=""> </span><span style="color: #cc524b;" class="">if</span><span style="color: #d4bfa0;" class=""> other'sTs </span><span style="color: #a3d349;" class="">>=</span><span style="color: #d4bfa0;" class=""> myTs</span></div><div class=""><span style="color: #d4bfa0;" class=""> </span><span style="color: #cc524b;" class="">then</span><span style="color: #d4bfa0;" class=""> return </span>()</div><div class=""><span style="color: #d4bfa0;" class=""> </span><span style="color: #cc524b;" class="">else</span><span style="color: #d4bfa0;" class=""> putAsNewTailOrDiscard other'sNxt</span></div><br class=""><div class=""><span style="color: #d4bfa0;" class=""> liftIO </span><span style="color: #a3d349;" class="">$</span><span style="color: #d4bfa0;" class=""> atomically </span><span style="color: #a3d349;" class="">$</span><span style="color: #d4bfa0;" class=""> putAsNewTailOrDiscard spotNxt</span></div><div class=""><span style="color: #d4bfa0;" class=""> return spotNxt</span></div><div class=""><span style="color: #d4bfa0;" class=""> </span><span style="color: #cc524b;" class="">where</span></div><div class=""><span style="color: #96b946;" class=""> </span><span style="color: #66a89d;" class="">justLatest</span><span style="color: #96b946;" class=""> </span><span style="color: #cc524b;font-weight: bold;" class="">::</span><span style="color: #96b946;" class=""> </span>(<span style="color: #82aed8;" class="">a</span><span style="color: #96b946;" class=""> </span><span style="color: #cc524b;font-weight: bold;" class="">-></span><span style="color: #96b946;" class=""> </span><span style="color: #6b95c5;" class="">Timestamp</span><span style="color: #96b946;" class=""> </span><span style="color: #cc524b;font-weight: bold;" class="">-></span><span style="color: #96b946;" class=""> </span><span style="color: #82aed8;" class="">a</span><span style="color: #96b946;" class=""> </span><span style="color: #cc524b;font-weight: bold;" class="">-></span><span style="color: #96b946;" class=""> </span><span style="color: #6b95c5;" class="">Timestamp</span><span style="color: #96b946;" class=""> </span><span style="color: #cc524b;font-weight: bold;" class="">-></span><span style="color: #96b946;" class=""> </span><span style="color: #82aed8;" class="">a</span>)</div><div class=""><span style="color: #d4bfa0;" class=""> justLatest _prevVal _prevTs spotVal _spotTs </span><span style="color: #cc524b;font-weight: bold;" class="">=</span><span style="color: #d4bfa0;" class=""> spotVal</span></div><br class=""><div class=""><span style="color: #7e6b5f;" class="">-- Each concurrent thread is supposed to have its local 'ValueSink' reference</span></div><div class=""><span style="color: #7e6b5f;" class="">-- "cached" over time, but keep in mind that for any such thread who is slow</span></div><div class=""><span style="color: #7e6b5f;" class="">-- in unfolding the value stream, the historical values will pile up in heap.</span></div><br class=""></div><div><br class=""><blockquote type="cite" class=""><div class="">On 2021-09-04, at 18:42, YueCompl <<a href="mailto:compl.yue@icloud.com" class="">compl.yue@icloud.com</a>> wrote:</div><br class="Apple-interchange-newline"><div class=""><meta http-equiv="Content-Type" content="text/html; charset=us-ascii" class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;" class=""><div class="">I'd like to add a new feature that you can fold the historic value stream in deriving the new state value, then it becomes:</div><div class=""><br class=""></div><div class=""><div style="color: rgb(212, 190, 152); background-color: rgb(23, 24, 24); font-family: Menlo, Monaco, "Courier New", monospace; line-height: 18px; white-space: pre;" class=""><br class=""><div class=""><span style="color: #cc524b;" class="">data</span><span style="color: #d4bfa0;" class=""> </span><span style="color: #6b95c5;" class="">ValueNode</span><span style="color: #d4bfa0;" class=""> </span><span style="color: #82aed8;" class="">a</span><span style="color: #d4bfa0;" class=""> </span><span style="color: #cc524b;font-weight: bold;" class="">=</span><span style="color: #d4bfa0;" class=""> </span><span style="color: #cca143;" class="">ValueNode</span></div><div class=""><span style="color: #d4bfa0;" class=""> </span><span style="color: #cca143;" class="">{</span><span style="color: #d4bfa0;" class=""> </span><span style="color: #cca143;" class="">node'value</span><span style="color: #d4bfa0;" class=""> </span><span style="color: #cc524b;font-weight: bold;" class="">::</span><span style="color: #d4bfa0;" class=""> </span><span style="color: #82aed8;" class="">a</span>,</div><div class=""><span style="color: #d4bfa0;" class=""> </span><span style="color: #cca143;" class="">node'timestamp</span><span style="color: #d4bfa0;" class=""> </span><span style="color: #cc524b;font-weight: bold;" class="">::</span><span style="color: #d4bfa0;" class=""> </span><span style="color: #6b95c5;" class="">Timestamp</span>,</div><div class=""><span style="color: #d4bfa0;" class=""> </span><span style="color: #cca143;" class="">node'next</span><span style="color: #d4bfa0;" class=""> </span><span style="color: #cc524b;font-weight: bold;" class="">::</span><span style="color: #d4bfa0;" class=""> </span><span style="color: #6b95c5;" class="">ValueSink</span><span style="color: #d4bfa0;" class=""> </span><span style="color: #82aed8;" class="">a</span></div><div class=""><span style="color: #d4bfa0;" class=""> </span><span style="color: #cca143;" class="">}</span></div><br class=""><div class=""><span style="color: #cc524b;" class="">type</span><span style="color: #d4bfa0;" class=""> </span><span style="color: #6b95c5;" class="">ValueSink</span><span style="color: #d4bfa0;" class=""> </span><span style="color: #82aed8;" class="">a</span><span style="color: #d4bfa0;" class=""> </span><span style="color: #cc524b;font-weight: bold;" class="">=</span><span style="color: #d4bfa0;" class=""> </span><span style="color: #6b95c5;" class="">TMVar</span><span style="color: #d4bfa0;" class=""> </span>(<span style="color: #6b95c5;" class="">ValueNode</span><span style="color: #d4bfa0;" class=""> </span><span style="color: #82aed8;" class="">a</span>)</div><br class=""><div class=""><span style="color: #cc524b;" class="">type</span><span style="color: #d4bfa0;" class=""> </span><span style="color: #6b95c5;" class="">Timestamp</span><span style="color: #d4bfa0;" class=""> </span><span style="color: #cc524b;font-weight: bold;" class="">=</span><span style="color: #d4bfa0;" class=""> </span><span style="color: #6b95c5;" class="">Int</span></div><br class=""><div class=""><span style="color: #66a89d;" class="">seekTail</span><span style="color: #96b946;" class=""> </span><span style="color: #cc524b;font-weight: bold;" class="">::</span></div><div class=""><span style="color: #96b946;" class=""> </span><span style="color: #cc524b;font-style: italic;" class="">forall</span><span style="color: #96b946;" class=""> </span><span style="color: #82aed8;" class="">a</span><span style="color: #cc524b;font-weight: bold;" class="">.</span></div><div class=""><span style="color: #96b946;" class=""> </span>(<span style="color: #82aed8;" class="">a</span><span style="color: #96b946;" class=""> </span><span style="color: #cc524b;font-weight: bold;" class="">-></span><span style="color: #96b946;" class=""> </span><span style="color: #6b95c5;" class="">Timestamp</span><span style="color: #96b946;" class=""> </span><span style="color: #cc524b;font-weight: bold;" class="">-></span><span style="color: #96b946;" class=""> </span><span style="color: #82aed8;" class="">a</span><span style="color: #96b946;" class=""> </span><span style="color: #cc524b;font-weight: bold;" class="">-></span><span style="color: #96b946;" class=""> </span><span style="color: #6b95c5;" class="">Timestamp</span><span style="color: #96b946;" class=""> </span><span style="color: #cc524b;font-weight: bold;" class="">-></span><span style="color: #96b946;" class=""> </span><span style="color: #82aed8;" class="">a</span>)<span style="color: #96b946;" class=""> </span><span style="color: #cc524b;font-weight: bold;" class="">-></span></div><div class=""><span style="color: #96b946;" class=""> </span><span style="color: #6b95c5;" class="">ValueSink</span><span style="color: #96b946;" class=""> </span><span style="color: #82aed8;" class="">a</span><span style="color: #96b946;" class=""> </span><span style="color: #cc524b;font-weight: bold;" class="">-></span></div><div class=""><span style="color: #96b946;" class=""> </span><span style="color: #6b95c5;" class="">STM</span><span style="color: #96b946;" class=""> </span>(<span style="color: #6b95c5;" class="">ValueSink</span><span style="color: #96b946;" class=""> </span><span style="color: #82aed8;" class="">a</span>,<span style="color: #96b946;" class=""> </span><span style="color: #6b95c5;" class="">Maybe</span><span style="color: #96b946;" class=""> </span>(<span style="color: #6b95c5;" class="">ValueNode</span><span style="color: #96b946;" class=""> </span><span style="color: #82aed8;" class="">a</span>))</div><div class=""><span style="color: #d4bfa0;" class="">seekTail f sink </span><span style="color: #cc524b;font-weight: bold;" class="">=</span><span style="color: #d4bfa0;" class=""> go sink </span><span style="color: #cca143;" class="">Nothing</span></div><div class=""><span style="color: #d4bfa0;" class=""> </span><span style="color: #cc524b;" class="">where</span></div><div class=""><span style="color: #96b946;" class=""> </span><span style="color: #66a89d;" class="">go</span><span style="color: #96b946;" class=""> </span><span style="color: #cc524b;font-weight: bold;" class="">::</span></div><div class=""><span style="color: #96b946;" class=""> </span><span style="color: #6b95c5;" class="">ValueSink</span><span style="color: #96b946;" class=""> </span><span style="color: #82aed8;" class="">a</span><span style="color: #96b946;" class=""> </span><span style="color: #cc524b;font-weight: bold;" class="">-></span></div><div class=""><span style="color: #96b946;" class=""> </span><span style="color: #6b95c5;" class="">Maybe</span><span style="color: #96b946;" class=""> </span>(<span style="color: #6b95c5;" class="">ValueNode</span><span style="color: #96b946;" class=""> </span><span style="color: #82aed8;" class="">a</span>)<span style="color: #96b946;" class=""> </span><span style="color: #cc524b;font-weight: bold;" class="">-></span></div><div class=""><span style="color: #96b946;" class=""> </span><span style="color: #6b95c5;" class="">STM</span><span style="color: #96b946;" class=""> </span>(<span style="color: #6b95c5;" class="">ValueSink</span><span style="color: #96b946;" class=""> </span><span style="color: #82aed8;" class="">a</span>,<span style="color: #96b946;" class=""> </span><span style="color: #6b95c5;" class="">Maybe</span><span style="color: #96b946;" class=""> </span>(<span style="color: #6b95c5;" class="">ValueNode</span><span style="color: #96b946;" class=""> </span><span style="color: #82aed8;" class="">a</span>))</div><div class=""><span style="color: #d4bfa0;" class=""> go ref prevNode </span><span style="color: #cc524b;font-weight: bold;" class="">=</span></div><div class=""><span style="color: #d4bfa0;" class=""> tryReadTMVar ref </span><span style="color: #a3d349;" class="">>>=</span><span style="color: #d4bfa0;" class=""> </span><span style="color: #cc524b;font-weight: bold;" class="">\</span><span style="color: #cc524b;" class="">case</span></div><div class=""><span style="color: #d4bfa0;" class=""> </span><span style="color: #cca143;" class="">Nothing</span><span style="color: #d4bfa0;" class=""> </span><span style="color: #cc524b;font-weight: bold;" class="">-></span><span style="color: #d4bfa0;" class=""> return </span>(<span style="color: #d4bfa0;" class="">ref</span>,<span style="color: #d4bfa0;" class=""> prevNode</span>)</div><div class=""><span style="color: #d4bfa0;" class=""> </span><span style="color: #cca143;" class="">Just</span><span style="color: #d4bfa0;" class=""> self</span><span style="color: #cca143;" class="">@</span>(<span style="color: #cca143;" class="">ValueNode</span><span style="color: #d4bfa0;" class=""> spotVal spotTs nxt</span>)<span style="color: #d4bfa0;" class=""> </span><span style="color: #cc524b;font-weight: bold;" class="">-></span></div><div class=""><span style="color: #d4bfa0;" class=""> go nxt </span><span style="color: #a3d349;" class="">$</span></div><div class=""><span style="color: #d4bfa0;" class=""> </span><span style="color: #cca143;" class="">Just</span></div><div class=""><span style="color: #d4bfa0;" class=""> self</span></div><div class=""><span style="color: #d4bfa0;" class=""> </span><span style="color: #cca143;" class="">{</span><span style="color: #d4bfa0;" class=""> </span><span style="color: #cca143;" class="">node'value</span><span style="color: #d4bfa0;" class=""> </span><span style="color: #cc524b;font-weight: bold;" class="">=</span><span style="color: #d4bfa0;" class=""> </span><span style="color: #cc524b;" class="">case</span><span style="color: #d4bfa0;" class=""> prevNode </span><span style="color: #cc524b;" class="">of</span></div><div class=""><span style="color: #d4bfa0;" class=""> </span><span style="color: #cca143;" class="">Nothing</span><span style="color: #d4bfa0;" class=""> </span><span style="color: #cc524b;font-weight: bold;" class="">-></span><span style="color: #d4bfa0;" class=""> spotVal</span></div><div class=""><span style="color: #d4bfa0;" class=""> </span><span style="color: #cca143;" class="">Just</span><span style="color: #d4bfa0;" class=""> </span>(<span style="color: #cca143;" class="">ValueNode</span><span style="color: #d4bfa0;" class=""> prevVal prevTs _prevNxt</span>)<span style="color: #d4bfa0;" class=""> </span><span style="color: #cc524b;font-weight: bold;" class="">-></span></div><div class=""><span style="color: #d4bfa0;" class=""> f prevVal prevTs spotVal spotTs</span></div><div class=""><span style="color: #d4bfa0;" class=""> </span><span style="color: #cca143;" class="">}</span></div><br class=""><div class=""><span style="color: #66a89d;" class="">updateValue</span><span style="color: #96b946;" class=""> </span><span style="color: #cc524b;font-weight: bold;" class="">::</span></div><div class=""><span style="color: #96b946;" class=""> </span><span style="color: #cc524b;font-style: italic;" class="">forall</span><span style="color: #96b946;" class=""> </span><span style="color: #82aed8;" class="">a</span><span style="color: #96b946;" class=""> </span><span style="color: #82aed8;" class="">m</span><span style="color: #cc524b;font-weight: bold;" class="">.</span></div><div class=""><span style="color: #96b946;" class=""> </span><span style="color: #6b95c5;" class="">MonadIO</span><span style="color: #96b946;" class=""> </span><span style="color: #82aed8;" class="">m</span><span style="color: #96b946;" class=""> </span><span style="color: #cc524b;font-weight: bold;" class="">=></span></div><div class=""><span style="color: #96b946;" class=""> </span>(<span style="color: #6b95c5;" class="">Maybe</span><span style="color: #96b946;" class=""> </span>(<span style="color: #82aed8;" class="">a</span>,<span style="color: #96b946;" class=""> </span><span style="color: #6b95c5;" class="">Timestamp</span>)<span style="color: #96b946;" class=""> </span><span style="color: #cc524b;font-weight: bold;" class="">-></span><span style="color: #96b946;" class=""> </span><span style="color: #82aed8;" class="">m</span><span style="color: #96b946;" class=""> </span>(<span style="color: #82aed8;" class="">a</span>,<span style="color: #96b946;" class=""> </span><span style="color: #6b95c5;" class="">Timestamp</span>))<span style="color: #96b946;" class=""> </span><span style="color: #cc524b;font-weight: bold;" class="">-></span></div><div class=""><span style="color: #96b946;" class=""> </span><span style="color: #6b95c5;" class="">ValueSink</span><span style="color: #96b946;" class=""> </span><span style="color: #82aed8;" class="">a</span><span style="color: #96b946;" class=""> </span><span style="color: #cc524b;font-weight: bold;" class="">-></span></div><div class=""><span style="color: #96b946;" class=""> </span><span style="color: #82aed8;" class="">m</span><span style="color: #96b946;" class=""> </span>()</div><div class=""><span style="color: #d4bfa0;" class="">updateValue f sink </span><span style="color: #cc524b;font-weight: bold;" class="">=</span><span style="color: #d4bfa0;" class=""> </span><span style="color: #cc524b;" class="">do</span></div><div class=""><span style="color: #d4bfa0;" class=""> </span>(<span style="color: #d4bfa0;" class="">tailRef</span>,<span style="color: #d4bfa0;" class=""> tailNode</span>)<span style="color: #d4bfa0;" class=""> </span><span style="color: #cc524b;font-weight: bold;" class=""><-</span><span style="color: #d4bfa0;" class=""> liftIO </span><span style="color: #a3d349;" class="">$</span><span style="color: #d4bfa0;" class=""> atomically </span><span style="color: #a3d349;" class="">$</span><span style="color: #d4bfa0;" class=""> seekTail justLatest sink</span></div><div class=""><span style="color: #d4bfa0;" class=""> </span><span style="color: #cc524b;" class="">case</span><span style="color: #d4bfa0;" class=""> tailNode </span><span style="color: #cc524b;" class="">of</span></div><div class=""><span style="color: #d4bfa0;" class=""> </span><span style="color: #cca143;" class="">Nothing</span><span style="color: #d4bfa0;" class=""> </span><span style="color: #cc524b;font-weight: bold;" class="">-></span><span style="color: #d4bfa0;" class=""> </span><span style="color: #cc524b;" class="">do</span></div><div class=""><span style="color: #d4bfa0;" class=""> </span>(<span style="color: #d4bfa0;" class="">myVal</span>,<span style="color: #d4bfa0;" class=""> myTs</span>)<span style="color: #d4bfa0;" class=""> </span><span style="color: #cc524b;font-weight: bold;" class=""><-</span><span style="color: #d4bfa0;" class=""> f </span><span style="color: #cca143;" class="">Nothing</span></div><div class=""><span style="color: #d4bfa0;" class=""> liftIO </span><span style="color: #a3d349;" class="">$</span></div><div class=""><span style="color: #d4bfa0;" class=""> atomically </span><span style="color: #a3d349;" class="">$</span><span style="color: #d4bfa0;" class=""> </span><span style="color: #cc524b;" class="">do</span></div><div class=""><span style="color: #d4bfa0;" class=""> nxt </span><span style="color: #cc524b;font-weight: bold;" class=""><-</span><span style="color: #d4bfa0;" class=""> newEmptyTMVar</span></div><div class=""><span style="color: #d4bfa0;" class=""> void </span><span style="color: #a3d349;" class="">$</span><span style="color: #d4bfa0;" class=""> tryPutTMVar tailRef </span><span style="color: #a3d349;" class="">$</span><span style="color: #d4bfa0;" class=""> </span><span style="color: #cca143;" class="">ValueNode</span><span style="color: #d4bfa0;" class=""> myVal myTs nxt</span></div><div class=""><span style="color: #d4bfa0;" class=""> </span><span style="color: #cca143;" class="">Just</span><span style="color: #d4bfa0;" class=""> </span>(<span style="color: #cca143;" class="">ValueNode</span><span style="color: #d4bfa0;" class=""> spotVal spotTs spotNxt</span>)<span style="color: #d4bfa0;" class=""> </span><span style="color: #cc524b;font-weight: bold;" class="">-></span><span style="color: #d4bfa0;" class=""> </span><span style="color: #cc524b;" class="">do</span></div><div class=""><span style="color: #d4bfa0;" class=""> </span>(<span style="color: #d4bfa0;" class="">myVal</span>,<span style="color: #d4bfa0;" class=""> myTs</span>)<span style="color: #d4bfa0;" class=""> </span><span style="color: #cc524b;font-weight: bold;" class=""><-</span><span style="color: #d4bfa0;" class=""> f </span><span style="color: #a3d349;" class="">$</span><span style="color: #d4bfa0;" class=""> </span><span style="color: #cca143;" class="">Just</span><span style="color: #d4bfa0;" class=""> </span>(<span style="color: #d4bfa0;" class="">spotVal</span>,<span style="color: #d4bfa0;" class=""> spotTs</span>)</div><div class=""><span style="color: #d4bfa0;" class=""> newNxt </span><span style="color: #cc524b;font-weight: bold;" class=""><-</span><span style="color: #d4bfa0;" class=""> liftIO newEmptyTMVarIO</span></div><div class=""><span style="color: #d4bfa0;" class=""> </span><span style="color: #cc524b;" class="">let</span><span style="color: #d4bfa0;" class=""> newTail </span><span style="color: #cc524b;font-weight: bold;" class="">=</span><span style="color: #d4bfa0;" class=""> </span><span style="color: #cca143;" class="">ValueNode</span><span style="color: #d4bfa0;" class=""> myVal myTs newNxt</span></div><br class=""><div class=""><span style="color: #96b946;" class=""> </span><span style="color: #66a89d;" class="">putAsNewTailOrDiscard</span><span style="color: #96b946;" class=""> </span><span style="color: #cc524b;font-weight: bold;" class="">::</span><span style="color: #96b946;" class=""> </span><span style="color: #6b95c5;" class="">ValueSink</span><span style="color: #96b946;" class=""> </span><span style="color: #82aed8;" class="">a</span><span style="color: #96b946;" class=""> </span><span style="color: #cc524b;font-weight: bold;" class="">-></span><span style="color: #96b946;" class=""> </span><span style="color: #6b95c5;" class="">STM</span><span style="color: #96b946;" class=""> </span>()</div><div class=""><span style="color: #d4bfa0;" class=""> putAsNewTailOrDiscard nodeRef </span><span style="color: #cc524b;font-weight: bold;" class="">=</span></div><div class=""><span style="color: #d4bfa0;" class=""> putTMVar nodeRef newTail </span><span style="color: #96b946;font-weight: bold;" class="">`</span><span style="color: #96b946;" class="">orElse</span><span style="color: #96b946;font-weight: bold;" class="">`</span><span style="color: #d4bfa0;" class=""> yetOther'sTail</span></div><div class=""><span style="color: #d4bfa0;" class=""> </span><span style="color: #cc524b;" class="">where</span></div><div class=""><span style="color: #d4bfa0;" class=""> yetOther'sTail </span><span style="color: #cc524b;font-weight: bold;" class="">=</span><span style="color: #d4bfa0;" class=""> </span><span style="color: #cc524b;" class="">do</span></div><div class=""><span style="color: #d4bfa0;" class=""> </span>(<span style="color: #cca143;" class="">ValueNode</span><span style="color: #d4bfa0;" class=""> _other'sVal other'sTs other'sNxt</span>)<span style="color: #d4bfa0;" class=""> </span><span style="color: #cc524b;font-weight: bold;" class=""><-</span></div><div class=""><span style="color: #d4bfa0;" class=""> readTMVar nodeRef</span></div><div class=""><span style="color: #d4bfa0;" class=""> </span><span style="color: #cc524b;" class="">if</span><span style="color: #d4bfa0;" class=""> other'sTs </span><span style="color: #a3d349;" class="">>=</span><span style="color: #d4bfa0;" class=""> myTs</span></div><div class=""><span style="color: #d4bfa0;" class=""> </span><span style="color: #cc524b;" class="">then</span><span style="color: #d4bfa0;" class=""> return </span>()</div><div class=""><span style="color: #d4bfa0;" class=""> </span><span style="color: #cc524b;" class="">else</span><span style="color: #d4bfa0;" class=""> putAsNewTailOrDiscard other'sNxt</span></div><br class=""><div class=""><span style="color: #d4bfa0;" class=""> liftIO </span><span style="color: #a3d349;" class="">$</span><span style="color: #d4bfa0;" class=""> atomically </span><span style="color: #a3d349;" class="">$</span><span style="color: #d4bfa0;" class=""> putAsNewTailOrDiscard spotNxt</span></div><div class=""><span style="color: #d4bfa0;" class=""> </span><span style="color: #cc524b;" class="">where</span></div><div class=""><span style="color: #96b946;" class=""> </span><span style="color: #66a89d;" class="">justLatest</span><span style="color: #96b946;" class=""> </span><span style="color: #cc524b;font-weight: bold;" class="">::</span><span style="color: #96b946;" class=""> </span>(<span style="color: #82aed8;" class="">a</span><span style="color: #96b946;" class=""> </span><span style="color: #cc524b;font-weight: bold;" class="">-></span><span style="color: #96b946;" class=""> </span><span style="color: #6b95c5;" class="">Timestamp</span><span style="color: #96b946;" class=""> </span><span style="color: #cc524b;font-weight: bold;" class="">-></span><span style="color: #96b946;" class=""> </span><span style="color: #82aed8;" class="">a</span><span style="color: #96b946;" class=""> </span><span style="color: #cc524b;font-weight: bold;" class="">-></span><span style="color: #96b946;" class=""> </span><span style="color: #6b95c5;" class="">Timestamp</span><span style="color: #96b946;" class=""> </span><span style="color: #cc524b;font-weight: bold;" class="">-></span><span style="color: #96b946;" class=""> </span><span style="color: #82aed8;" class="">a</span>)</div><div class=""><span style="color: #d4bfa0;" class=""> justLatest _prevVal _prevTs spotVal _spotTs </span><span style="color: #cc524b;font-weight: bold;" class="">=</span><span style="color: #d4bfa0;" class=""> spotVal</span></div><br class=""><div class=""><span style="color: #7e6b5f;" class="">-- Each concurrent thread is supposed to have its local 'ValueSink' reference</span></div><div class=""><span style="color: #7e6b5f;" class="">-- "cached" over time, but keep in mind that for any such thread who is slow</span></div><div class=""><span style="color: #7e6b5f;" class="">-- in unfolding the value stream, the historical values will pile up in heap.</span></div><br class=""></div></div><br class=""><div class=""><br class=""><blockquote type="cite" class=""><div class="">On 2021-09-03, at 16:26, YueCompl <<a href="mailto:compl.yue@icloud.com" class="">compl.yue@icloud.com</a>> wrote:</div><br class="Apple-interchange-newline"><div class=""><meta http-equiv="Content-Type" content="text/html; charset=us-ascii" class=""><div style="word-wrap: break-word; -webkit-nbsp-mode: space; line-break: after-white-space;" class="">It's a bit sad that I'm not so mathematically minded to understand you in that abstract level. But I have a more imperative solution in my mind, wrt the question:<div class=""><br class=""></div><div class=""><blockquote type="cite" class="">"server, tell me if there is a value of x newer than t." </blockquote></div><div class=""><br class=""></div><div class="">and do further mutate-or-giveup, like this:</div><div class=""><br class=""></div><div class=""><div style="color: rgb(212, 190, 152); background-color: rgb(23, 24, 24); font-family: Menlo, Monaco, "Courier New", monospace; line-height: 18px; white-space: pre;" class=""><br class=""><div class=""><span style="color: #cc524b;" class="">data</span><span style="color: #d4bfa0;" class=""> </span><span style="color: #6b95c5;" class="">ValueNode</span><span style="color: #d4bfa0;" class=""> </span><span style="color: #82aed8;" class="">a</span><span style="color: #d4bfa0;" class=""> </span><span style="color: #cc524b;font-weight: bold;" class="">=</span><span style="color: #d4bfa0;" class=""> </span><span style="color: #cca143;" class="">ValueNode</span></div><div class=""><span style="color: #d4bfa0;" class=""> </span><span style="color: #cca143;" class="">{</span><span style="color: #d4bfa0;" class=""> </span><span style="color: #cca143;" class="">node'value</span><span style="color: #d4bfa0;" class=""> </span><span style="color: #cc524b;font-weight: bold;" class="">::</span><span style="color: #d4bfa0;" class=""> </span><span style="color: #82aed8;" class="">a</span>,</div><div class=""><span style="color: #d4bfa0;" class=""> </span><span style="color: #cca143;" class="">node'timestamp</span><span style="color: #d4bfa0;" class=""> </span><span style="color: #cc524b;font-weight: bold;" class="">::</span><span style="color: #d4bfa0;" class=""> </span><span style="color: #6b95c5;" class="">Timestamp</span>,</div><div class=""><span style="color: #d4bfa0;" class=""> </span><span style="color: #cca143;" class="">node'next</span><span style="color: #d4bfa0;" class=""> </span><span style="color: #cc524b;font-weight: bold;" class="">::</span><span style="color: #d4bfa0;" class=""> </span><span style="color: #6b95c5;" class="">ValueSink</span><span style="color: #d4bfa0;" class=""> </span><span style="color: #82aed8;" class="">a</span></div><div class=""><span style="color: #d4bfa0;" class=""> </span><span style="color: #cca143;" class="">}</span></div><br class=""><div class=""><span style="color: #cc524b;" class="">type</span><span style="color: #d4bfa0;" class=""> </span><span style="color: #6b95c5;" class="">ValueSink</span><span style="color: #d4bfa0;" class=""> </span><span style="color: #82aed8;" class="">a</span><span style="color: #d4bfa0;" class=""> </span><span style="color: #cc524b;font-weight: bold;" class="">=</span><span style="color: #d4bfa0;" class=""> </span><span style="color: #6b95c5;" class="">TMVar</span><span style="color: #d4bfa0;" class=""> </span>(<span style="color: #6b95c5;" class="">ValueNode</span><span style="color: #d4bfa0;" class=""> </span><span style="color: #82aed8;" class="">a</span>)</div><br class=""><div class=""><span style="color: #cc524b;" class="">type</span><span style="color: #d4bfa0;" class=""> </span><span style="color: #6b95c5;" class="">Timestamp</span><span style="color: #d4bfa0;" class=""> </span><span style="color: #cc524b;font-weight: bold;" class="">=</span><span style="color: #d4bfa0;" class=""> </span><span style="color: #6b95c5;" class="">Int</span></div><br class=""><div class=""><span style="color: #66a89d;" class="">seekTail</span><span style="color: #96b946;" class=""> </span><span style="color: #cc524b;font-weight: bold;" class="">::</span><span style="color: #96b946;" class=""> </span><span style="color: #6b95c5;" class="">ValueSink</span><span style="color: #96b946;" class=""> </span><span style="color: #82aed8;" class="">a</span><span style="color: #96b946;" class=""> </span><span style="color: #cc524b;font-weight: bold;" class="">-></span><span style="color: #96b946;" class=""> </span><span style="color: #6b95c5;" class="">STM</span><span style="color: #96b946;" class=""> </span>(<span style="color: #6b95c5;" class="">ValueSink</span><span style="color: #96b946;" class=""> </span><span style="color: #82aed8;" class="">a</span>,<span style="color: #96b946;" class=""> </span><span style="color: #6b95c5;" class="">Maybe</span><span style="color: #96b946;" class=""> </span>(<span style="color: #6b95c5;" class="">ValueNode</span><span style="color: #96b946;" class=""> </span><span style="color: #82aed8;" class="">a</span>))</div><div class=""><span style="color: #d4bfa0;" class="">seekTail sink </span><span style="color: #cc524b;font-weight: bold;" class="">=</span><span style="color: #d4bfa0;" class=""> go sink </span><span style="color: #cca143;" class="">Nothing</span></div><div class=""><span style="color: #d4bfa0;" class=""> </span><span style="color: #cc524b;" class="">where</span></div><div class=""><span style="color: #d4bfa0;" class=""> go ref ancestor </span><span style="color: #cc524b;font-weight: bold;" class="">=</span></div><div class=""><span style="color: #d4bfa0;" class=""> tryReadTMVar ref </span><span style="color: #a3d349;" class="">>>=</span><span style="color: #d4bfa0;" class=""> </span><span style="color: #cc524b;font-weight: bold;" class="">\</span><span style="color: #cc524b;" class="">case</span></div><div class=""><span style="color: #d4bfa0;" class=""> </span><span style="color: #cca143;" class="">Nothing</span><span style="color: #d4bfa0;" class=""> </span><span style="color: #cc524b;font-weight: bold;" class="">-></span><span style="color: #d4bfa0;" class=""> return </span>(<span style="color: #d4bfa0;" class="">ref</span>,<span style="color: #d4bfa0;" class=""> ancestor</span>)</div><div class=""><span style="color: #d4bfa0;" class=""> </span><span style="color: #cca143;" class="">Just</span><span style="color: #d4bfa0;" class=""> self</span><span style="color: #cca143;" class="">@</span>(<span style="color: #cca143;" class="">ValueNode</span><span style="color: #d4bfa0;" class=""> _ _ nxt</span>)<span style="color: #d4bfa0;" class=""> </span><span style="color: #cc524b;font-weight: bold;" class="">-></span><span style="color: #d4bfa0;" class=""> go nxt </span><span style="color: #a3d349;" class="">$</span><span style="color: #d4bfa0;" class=""> </span><span style="color: #cca143;" class="">Just</span><span style="color: #d4bfa0;" class=""> self</span></div><br class=""><div class=""><span style="color: #66a89d;" class="">updateValue</span><span style="color: #96b946;" class=""> </span><span style="color: #cc524b;font-weight: bold;" class="">::</span></div><div class=""><span style="color: #96b946;" class=""> </span><span style="color: #cc524b;font-style: italic;" class="">forall</span><span style="color: #96b946;" class=""> </span><span style="color: #82aed8;" class="">a</span><span style="color: #96b946;" class=""> </span><span style="color: #82aed8;" class="">m</span><span style="color: #cc524b;font-weight: bold;" class="">.</span></div><div class=""><span style="color: #96b946;" class=""> </span><span style="color: #6b95c5;" class="">MonadIO</span><span style="color: #96b946;" class=""> </span><span style="color: #82aed8;" class="">m</span><span style="color: #96b946;" class=""> </span><span style="color: #cc524b;font-weight: bold;" class="">=></span></div><div class=""><span style="color: #96b946;" class=""> </span>(<span style="color: #6b95c5;" class="">Maybe</span><span style="color: #96b946;" class=""> </span>(<span style="color: #82aed8;" class="">a</span>,<span style="color: #96b946;" class=""> </span><span style="color: #6b95c5;" class="">Timestamp</span>)<span style="color: #96b946;" class=""> </span><span style="color: #cc524b;font-weight: bold;" class="">-></span><span style="color: #96b946;" class=""> </span><span style="color: #82aed8;" class="">m</span><span style="color: #96b946;" class=""> </span>(<span style="color: #82aed8;" class="">a</span>,<span style="color: #96b946;" class=""> </span><span style="color: #6b95c5;" class="">Timestamp</span>))<span style="color: #96b946;" class=""> </span><span style="color: #cc524b;font-weight: bold;" class="">-></span></div><div class=""><span style="color: #96b946;" class=""> </span><span style="color: #6b95c5;" class="">ValueSink</span><span style="color: #96b946;" class=""> </span><span style="color: #82aed8;" class="">a</span><span style="color: #96b946;" class=""> </span><span style="color: #cc524b;font-weight: bold;" class="">-></span></div><div class=""><span style="color: #96b946;" class=""> </span><span style="color: #82aed8;" class="">m</span><span style="color: #96b946;" class=""> </span>()</div><div class=""><span style="color: #d4bfa0;" class="">updateValue f sink </span><span style="color: #cc524b;font-weight: bold;" class="">=</span><span style="color: #d4bfa0;" class=""> </span><span style="color: #cc524b;" class="">do</span></div><div class=""><span style="color: #d4bfa0;" class=""> </span>(<span style="color: #d4bfa0;" class="">tailRef</span>,<span style="color: #d4bfa0;" class=""> tailNode</span>)<span style="color: #d4bfa0;" class=""> </span><span style="color: #cc524b;font-weight: bold;" class=""><-</span><span style="color: #d4bfa0;" class=""> liftIO </span><span style="color: #a3d349;" class="">$</span><span style="color: #d4bfa0;" class=""> atomically </span><span style="color: #a3d349;" class="">$</span><span style="color: #d4bfa0;" class=""> seekTail sink</span></div><div class=""><span style="color: #d4bfa0;" class=""> </span><span style="color: #cc524b;" class="">case</span><span style="color: #d4bfa0;" class=""> tailNode </span><span style="color: #cc524b;" class="">of</span></div><div class=""><span style="color: #d4bfa0;" class=""> </span><span style="color: #cca143;" class="">Nothing</span><span style="color: #d4bfa0;" class=""> </span><span style="color: #cc524b;font-weight: bold;" class="">-></span><span style="color: #d4bfa0;" class=""> </span><span style="color: #cc524b;" class="">do</span></div><div class=""><span style="color: #d4bfa0;" class=""> </span>(<span style="color: #d4bfa0;" class="">myVal</span>,<span style="color: #d4bfa0;" class=""> myTs</span>)<span style="color: #d4bfa0;" class=""> </span><span style="color: #cc524b;font-weight: bold;" class=""><-</span><span style="color: #d4bfa0;" class=""> f </span><span style="color: #cca143;" class="">Nothing</span></div><div class=""><span style="color: #d4bfa0;" class=""> liftIO </span><span style="color: #a3d349;" class="">$</span></div><div class=""><span style="color: #d4bfa0;" class=""> atomically </span><span style="color: #a3d349;" class="">$</span><span style="color: #d4bfa0;" class=""> </span><span style="color: #cc524b;" class="">do</span></div><div class=""><span style="color: #d4bfa0;" class=""> nxt </span><span style="color: #cc524b;font-weight: bold;" class=""><-</span><span style="color: #d4bfa0;" class=""> newEmptyTMVar</span></div><div class=""><span style="color: #d4bfa0;" class=""> void </span><span style="color: #a3d349;" class="">$</span><span style="color: #d4bfa0;" class=""> tryPutTMVar tailRef </span><span style="color: #a3d349;" class="">$</span><span style="color: #d4bfa0;" class=""> </span><span style="color: #cca143;" class="">ValueNode</span><span style="color: #d4bfa0;" class=""> myVal myTs nxt</span></div><div class=""><span style="color: #d4bfa0;" class=""> </span><span style="color: #cca143;" class="">Just</span><span style="color: #d4bfa0;" class=""> </span>(<span style="color: #cca143;" class="">ValueNode</span><span style="color: #d4bfa0;" class=""> seenVal seenTs seenNxt</span>)<span style="color: #d4bfa0;" class=""> </span><span style="color: #cc524b;font-weight: bold;" class="">-></span><span style="color: #d4bfa0;" class=""> </span><span style="color: #cc524b;" class="">do</span></div><div class=""><span style="color: #d4bfa0;" class=""> </span>(<span style="color: #d4bfa0;" class="">myVal</span>,<span style="color: #d4bfa0;" class=""> myTs</span>)<span style="color: #d4bfa0;" class=""> </span><span style="color: #cc524b;font-weight: bold;" class=""><-</span><span style="color: #d4bfa0;" class=""> f </span><span style="color: #a3d349;" class="">$</span><span style="color: #d4bfa0;" class=""> </span><span style="color: #cca143;" class="">Just</span><span style="color: #d4bfa0;" class=""> </span>(<span style="color: #d4bfa0;" class="">seenVal</span>,<span style="color: #d4bfa0;" class=""> seenTs</span>)</div><div class=""><span style="color: #d4bfa0;" class=""> newNxt </span><span style="color: #cc524b;font-weight: bold;" class=""><-</span><span style="color: #d4bfa0;" class=""> liftIO newEmptyTMVarIO</span></div><div class=""><span style="color: #d4bfa0;" class=""> </span><span style="color: #cc524b;" class="">let</span><span style="color: #d4bfa0;" class=""> newTail </span><span style="color: #cc524b;font-weight: bold;" class="">=</span><span style="color: #d4bfa0;" class=""> </span><span style="color: #cca143;" class="">ValueNode</span><span style="color: #d4bfa0;" class=""> myVal myTs newNxt</span></div><br class=""><div class=""><span style="color: #96b946;" class=""> </span><span style="color: #66a89d;" class="">putAsNewTailOrDiscard</span><span style="color: #96b946;" class=""> </span><span style="color: #cc524b;font-weight: bold;" class="">::</span><span style="color: #96b946;" class=""> </span><span style="color: #6b95c5;" class="">ValueSink</span><span style="color: #96b946;" class=""> </span><span style="color: #82aed8;" class="">a</span><span style="color: #96b946;" class=""> </span><span style="color: #cc524b;font-weight: bold;" class="">-></span><span style="color: #96b946;" class=""> </span><span style="color: #6b95c5;" class="">STM</span><span style="color: #96b946;" class=""> </span>()</div><div class=""><span style="color: #d4bfa0;" class=""> putAsNewTailOrDiscard nodeRef </span><span style="color: #cc524b;font-weight: bold;" class="">=</span></div><div class=""><span style="color: #d4bfa0;" class=""> putTMVar nodeRef newTail </span><span style="color: #96b946;font-weight: bold;" class="">`</span><span style="color: #96b946;" class="">orElse</span><span style="color: #96b946;font-weight: bold;" class="">`</span><span style="color: #d4bfa0;" class=""> yetOther'sTail</span></div><div class=""><span style="color: #d4bfa0;" class=""> </span><span style="color: #cc524b;" class="">where</span></div><div class=""><span style="color: #d4bfa0;" class=""> yetOther'sTail </span><span style="color: #cc524b;font-weight: bold;" class="">=</span><span style="color: #d4bfa0;" class=""> </span><span style="color: #cc524b;" class="">do</span></div><div class=""><span style="color: #d4bfa0;" class=""> </span>(<span style="color: #cca143;" class="">ValueNode</span><span style="color: #d4bfa0;" class=""> _other'sVal other'sTs other'sNxt</span>)<span style="color: #d4bfa0;" class=""> </span><span style="color: #cc524b;font-weight: bold;" class=""><-</span></div><div class=""><span style="color: #d4bfa0;" class=""> readTMVar nodeRef</span></div><div class=""><span style="color: #d4bfa0;" class=""> </span><span style="color: #cc524b;" class="">if</span><span style="color: #d4bfa0;" class=""> other'sTs </span><span style="color: #a3d349;" class="">>=</span><span style="color: #d4bfa0;" class=""> myTs</span></div><div class=""><span style="color: #d4bfa0;" class=""> </span><span style="color: #cc524b;" class="">then</span><span style="color: #d4bfa0;" class=""> return </span>()</div><div class=""><span style="color: #d4bfa0;" class=""> </span><span style="color: #cc524b;" class="">else</span><span style="color: #d4bfa0;" class=""> putAsNewTailOrDiscard other'sNxt</span></div><br class=""><div class=""><span style="color: #d4bfa0;" class=""> liftIO </span><span style="color: #a3d349;" class="">$</span><span style="color: #d4bfa0;" class=""> atomically </span><span style="color: #a3d349;" class="">$</span><span style="color: #d4bfa0;" class=""> putAsNewTailOrDiscard seenNxt</span></div><br class=""><div class=""><span style="color: #7e6b5f;" class="">-- Each concurrent thread is supposed to have its local 'ValueSink' reference</span></div><div class=""><span style="color: #7e6b5f;" class="">-- "cached" over time, but keep in mind that for any such thread who is slow</span></div><div class=""><span style="color: #7e6b5f;" class="">-- in unfolding the value stream, the historical values will pile up in heap.</span></div><br class=""></div></div><div class=""><br class=""><div class=""><br class=""><blockquote type="cite" class=""><div class="">On 2021-09-03, at 01:42, Olaf Klinke <<a href="mailto:olf@aatal-apotheke.de" class="">olf@aatal-apotheke.de</a>> wrote:</div><br class="Apple-interchange-newline"><div class=""><div class="">On Fri, 2021-09-03 at 00:00 +0800, YueCompl wrote:<br class=""><blockquote type="cite" class="">Um, I'm not sure I understand your case right, but if the "mutation" instead of the "mutated result" can be (might non-trivially) computed from a possibly outdated state, and the "mutation" can be trivially applied, I think `modifyTVar'` is the way to go. `readTVar` can be used to obtain an almost up-to-date state on demand, at low frequency.<br class=""></blockquote><br class="">To be concrete, my state is a collection of time stamped values, where<br class="">the monoid operation overwrites old values with new ones. <br class="">But I need to know the current state (x,t) to determine the "mutation",<br class="">because I'll be asking questions like "server, tell me if there is a<br class="">value of x newer than t." <br class="">Any observer whose initial state is synchronized with the worker thread<br class="">can in principle re-construct the worker's internal state by observing<br class="">the stream of emitted "mutations". <br class=""><br class="">The most general abstraction would be that of a monoid action on a<br class="">type, but in my case the monoid (mutations) and the mutated type are<br class="">identical. <br class=""><br class="">act :: m -> a -> a<br class="">act memtpy = id<br class="">act (x <> y) = act x . act y -- monoid homomorphism<br class="">act (x <> x) = act x -- idempotent<br class=""><br class="">Olaf<br class=""><br class=""></div></div></blockquote></div><br class=""></div></div></div></blockquote></div><br class=""></div></div></blockquote></div><br class=""></div></div></body></html>