<div style="min-height:22px;margin-bottom:8px;">But if you force the pair result, you have to evaluate modifying function isn't it? That's sometime unwanted when you have an very expensive f here, let's say a deep binary search which might not depend previous result.</div><div style="min-height:22px;margin-bottom:8px;"><br></div><div style="min-height:22px;margin-bottom:8px;">I think that is also why current atomicModifyIORef is designed this way, so I'd rather keep it the old way.</div><div style="min-height:22px;margin-bottom:8px;"><br></div><span class="mail-footer" aria-hidden="true">发自我的iPhone</span><div id="original-content"><br><br><div><div style="font-size:70%;padding:2px 0;">------------------ Original ------------------</div><div style="font-size:70%;background:#f0f0f0;color:#212121;padding:8px;border-radius:4px"><div><b>From:</b> David Feuer <david.feuer@gmail.com></div><div><b>Date:</b> Thu,Jul 12,2018 0:51 AM</div><div><b>To:</b> winter <drkoster@qq.com></div><div><b>Cc:</b> Haskell Libraries <libraries@haskell.org></div><div><b>Subject:</b> Re: Discussion: New atomic IORef functions</div></div></div><br><div dir="auto"><div>All the fundamental functions I've defined can be usefully used in the base library. I think that's one good reason to put them there. Another is that while the basic array operations have traditionally been exposed through array, vector, and primitive, and the basic TVar operations have been exposed through stm, the basic IORef and MVar operations have been exposed through base (except, for some reason, casMutVar#). I see no reason to change that.</div><div dir="auto"><br></div><div dir="auto">I never proposed a function that forces the previous value unnecessarily, so I don't know why you're complaining about that. The extra laziness I don't like is in the pair result; none of the uses I've seen thus can far make intentional use of that. That's why I tend to think atomicModifyIORef (as it exists today) is almost never what people actually want.</div><div dir="auto"><br></div><div dir="auto">Squeezing into a second component leads to extra allocation in what may be a performance-critical function; that said, I'm willing to hold off on higher tuples for now.<br><br><div class="gmail_quote" dir="auto"><div dir="ltr">On Sun, Jul 8, 2018, 3:36 AM winter <<a href="mailto:drkoster@qq.com">drkoster@qq.com</a>> wrote:<br></div><blockquote class="gmail_quote" style="border-left-width: 1px; border-left-style: solid; border-left-color: rgb(204, 204, 204); margin: 0px 0px 0px 6.693749904632568px; padding: 14px 16px 14px 8.3671875px; color: rgb(149, 149, 149); background-color: rgb(245, 246, 250);">
  
    
  
  <div bgcolor="#FFFFFF" text="#000000">
    <p>I believe new variations should always be motivated by use-case
      if there're too many choices, the lazy behavior of old
      `atomicModifyIORef` is justified by some cases the modifying
      functions are lazy in its argument, thus a lazy version could win
      by not forcing previous thunks, we'd want to keep its behavior as
      how it's documented.<br>
    </p>
    <p>As for tuples more than pairs, they're not really needed, user
      can always squeeze their product into `b` component. <br>
    </p>
    <p>IMHO only the addition of `atomicModifyIORef_` is sensible in the
      context of base, other APIs may go to package like primitives. But
      if you have a motivated use case with `atomicModifyIORef2`, etc.
      Please tell me.</p>
    <br>
    <div class="m_-1704689133044993229moz-cite-prefix">On 2018年07月08日 03:09, David Feuer
      wrote:<br>
    </div>
    <blockquote type="cite" style="margin: 0px 0px 0px 6.693749904632568px; padding: 14px 16px 14px 8.3671875px; color: rgb(149, 149, 149); background-color: rgb(245, 246, 250);">
      <div dir="auto">Whoops! I left out the proposal link:
        <div dir="auto"><br>
        </div>
        <div dir="auto"><a href="https://github.com/ghc-proposals/ghc-proposals/pull/149" rel="noreferrer" target="_blank">https://github.com/ghc-proposals/ghc-proposals/pull/149</a><br>
        </div>
        <div dir="auto"><br>
        </div>
        <div dir="auto">Also, what I called atomicModifyIORef_ below
          should really be called something like atomicModifyIORef'_, since it
            forces a polymorphic value.</div>
        <div dir="auto"><br>
          </div>
        <div dir="auto">Another
            thing to note: the underlying atomicModifyMutVar2# primop
            actually supports more than just pairs. It can handle
            triples, solos, and any other record types whose first
            components are lifted:</div>
        <div dir="auto"><br>
          </div>
        <div dir="auto">atomicModifyIORefSoloLazy</div>
        <div dir="auto">  :: IORef
            a -> (a -> Solo a) -> IO (Solo a)</div>
        <div dir="auto"><br>
          </div>
        <div dir="auto">
          <div dir="auto" style="font-family:sans-serif">atomicModifyIORefSolo</div>
          <div dir="auto" style="font-family:sans-serif">  :: IORef a
            -> (a -> Solo a) -> IO a</div>
          <div dir="auto" style="font-family:sans-serif"><br>
          </div>
          <div dir="auto" style="font-family:sans-serif">
            <div dir="auto">atomicModifyIORef3, atomicModifyIORef3Lazy</div>
            <div dir="auto">  :: IORef a -> (a -> (a, b, c)) ->
              IO (a, b, c)</div>
            <div dir="auto"><br>
            </div>
            <div dir="auto">etc.</div>
            <div dir="auto"><br>
            </div>
            <div dir="auto">Should we add any such?</div>
          </div>
        </div>
      </div>
      <br>
      <div class="gmail_quote">
        <div dir="ltr">On Sat, Jul 7, 2018, 2:35 PM David Feuer <<a href="mailto:david.feuer@gmail.com" rel="noreferrer" target="_blank">david.feuer@gmail.com</a>>
          wrote:<br>
        </div>
        <blockquote class="gmail_quote" style="border-left-width: 1px; border-left-style: solid; border-left-color: rgb(204, 204, 204); margin: 0px 0px 0px 6.693749904632568px; padding: 14px 16px 14px 8.3671875px; color: rgb(149, 149, 149); background-color: rgb(245, 246, 250);">
          <div dir="auto">I have proposed[1] the replacement of the
            atomicModifyMutVar# primop, and the addition of two cheaper
            but less capable ones. It seems likely that the proposal
            will succeed, but that the GHC steering committee will leave
            the question of user interface changes to the libraries
            list. I would like to open the discussion here.
            <div dir="auto"><br>
            </div>
            <div dir="auto">The new primops lead naturally to several
              thin wrappers:</div>
            <div dir="auto"><br>
            </div>
            <div dir="auto">-- Atomically replace the IORef contents</div>
            <div dir="auto">-- with the first component of the result of</div>
            <div dir="auto">-- applying the function to the old
              contents.</div>
            <div dir="auto">-- Return the old value and the result of</div>
            <div dir="auto">-- applying the function, without forcing
              the latter.</div>
            <div dir="auto">--</div>
            <div dir="auto">-- atomicModifyIORef ref f = do</div>
            <div dir="auto">--   (_old, ~(_new, res)) <-
              atomicModifyIORef2Lazy ref f</div>
            <div dir="auto">--   return res</div>
            <div dir="auto">atomicModifyIORef2Lazy</div>
            <div dir="auto">  :: IORef a -> (a -> (a, b)) -> IO
              (a, (a, b))</div>
            <div dir="auto"><br>
            </div>
            <div dir="auto">-- Atomically replace the IORef contents</div>
            <div dir="auto">-- with the result of applying the function</div>
            <div dir="auto">-- to the old contents. Return the old and</div>
            <div dir="auto">-- new contents without forcing the latter.</div>
            <div dir="auto">atomicModifyIORefLazy_</div>
            <div dir="auto">  :: IORef a -> (a -> a) -> IO (a,
              a)</div>
            <div dir="auto"><br>
            </div>
            <div dir="auto">-- Atomically replace the IORef contents</div>
            <div dir="auto">-- with the given value and return the old</div>
            <div dir="auto">-- contents.</div>
            <div dir="auto">--</div>
            <div dir="auto">-- atomicWriteIORef ref x = void
              (atomicSwapIORef ref x)</div>
            <div dir="auto">atomicSwapIORef</div>
            <div dir="auto">  :: IORef a -> a -> IO a</div>
            <div dir="auto"><br>
            </div>
            <div dir="auto">Based on the code I've read that uses
              atomicModifyIORef, I believe that the complete laziness
              of atomicModifyIORef2Lazy and atomicModifyIORefLazy_ is
              very rarely desirable. I therefore believe we should also
              (or perhaps instead?) offer stricter versions:</div>
            <div dir="auto"><br>
            </div>
            <div dir="auto">
              <div dir="auto" style="font-family:sans-serif">atomicModifyIORef2</div>
              <div dir="auto" style="font-family:sans-serif">  :: IORef
                a -> (a -> (a, b)) -> IO (a, (a, b))</div>
              <div dir="auto" style="font-family:sans-serif">atomicModifyIORef2
                ref f = do</div>
              <div dir="auto" style="font-family:sans-serif">  r@(_old,
                (_new, _res)) <- atomicModifyIORef2Lazy ref f</div>
              <div dir="auto" style="font-family:sans-serif">  return r</div>
              <div dir="auto" style="font-family:sans-serif"><br>
              </div>
              <div dir="auto" style="font-family:sans-serif">
                <div dir="auto">atomicModifyIORef_</div>
                <div dir="auto">  :: IORef a -> (a -> a) -> IO
                  (a, a)</div>
                <div dir="auto">atomicModifyIORef_ ref f = do</div>
                <div dir="auto">  r@(_old, !_new) <-
                  atomicModifyIORefLazy_ ref f</div>
                <div dir="auto">  return r</div>
                <div dir="auto"><br>
                </div>
                <div dir="auto">The classic atomicModifyIORef also
                  admits a less gratuitously lazy version:</div>
                <div dir="auto"><br>
                </div>
                <div dir="auto">atomicModifyIORefNGL</div>
                <div dir="auto">  :: IORef a -> (a -> (a,b)) ->
                  IO b</div>
                <div dir="auto">atomicModifyIORefNGL ref f = do</div>
                <div dir="auto">  (_old, (_new, res)) <-
                  atomicModifyIORef2 ref f</div>
                <div dir="auto">  return res</div>
                <div dir="auto"><br>
                </div>
                <div dir="auto">Should we add that as well (with a
                  better name)? Should we even consider *replacing* the
                  current atomicModifyIORef with that version? That
                  could theoretically break existing code, but I suspect
                  it would do so very rarely. If we don't change the
                  existing atomicModifyIORef now, I think we should
                  consider deprecating it: it's very easy to
                  accidentally use it too lazily.</div>
              </div>
            </div>
          </div>
        </blockquote>
      </div>
      <br>
      <fieldset class="m_-1704689133044993229mimeAttachmentHeader"></fieldset>
      <br>
      <pre>_______________________________________________
Libraries mailing list
<a class="m_-1704689133044993229moz-txt-link-abbreviated" href="mailto:Libraries@haskell.org" rel="noreferrer" target="_blank">Libraries@haskell.org</a>
<a class="m_-1704689133044993229moz-txt-link-freetext" href="http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries" rel="noreferrer" target="_blank">http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries</a>
</pre>
    </blockquote>
    <br>
  </div>

_______________________________________________<br>
Libraries mailing list<br>
<a href="mailto:Libraries@haskell.org" rel="noreferrer" target="_blank">Libraries@haskell.org</a><br>
<a href="http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries" rel="noreferrer noreferrer" target="_blank">http://mail.haskell.org/cgi-bin/mailman/listinfo/libraries</a><br>
</blockquote></div></div></div>

</div>