What do you think about the version that takes a function as an argument, and is optimized for the case where that's a selector? That really feels like the platonic ideal here.
On Mon, Oct 14, 2019, 6:35 PM Simon Peyton Jones <simo...@microsoft.com> wrote: > OK. I propose: > > > > - To give atomicModieyMutVarOf# its proper type, with a pair, as in > the proposal. > - To do that I’ll fiddle with genprimopcode, to allow it to parse > tuples as well as unboxed tuples; not hard. > - This would disallow all this stuff about “any type that has a first > field looking like a”, restricting to pairs alone. This didn’t form part > of the proposal, and was never documented. > - Add a bit more clarity to the documentation, so it’d clear what must > be forced. > > > > Any objections? > > > > Simon > > > > *From:* David Feuer <david.fe...@gmail.com> > *Sent:* 12 October 2019 00:00 > *To:* Simon Peyton Jones <simo...@microsoft.com> > *Cc:* ghc-devs <ghc-devs@haskell.org> > *Subject:* Re: atomicModifyMutVar2 > > > > I don't remember what documentation, if any, it has. You're right that > taking advantage of it is potentially risky. Here's what I think we really > want: > > > > atomicModifyMutVarQ# :: MutVar# s a -> (q -> a) -> (a -> q) -> State# > s -> (# State# s, a, q #) > > > > where there's a special rule that (q -> a) is "obviously" a selector that > selects a pointer. > > On Fri, Oct 11, 2019, 12:56 PM Simon Peyton Jones <simo...@microsoft.com> > wrote: > > The result doesn't have to be a pair. It can be a tuple of any size at > all. Indeed, it can even be an arbitrary record type whose first pointer > field has the appropriate type. > > > > I think that is 100.0% undocumented, in the code, or in the proposal. Are > you sure this is a settled consensus among the interested parties? > > > > Adopting it would impose new invariants on the representation of values in > GHC that I am deeply reluctant to impose. I would much much prefer to > stick with the pair that is (somewhat) documented. > > > > About pair vs Unit, yes, I can see (just) your point about why a pair > might be useful. Here’s a better example: > > > > Suppose mv :: MutVar# Int > > > > atomicModifyMutVar2# mv $ \a -> > > let foo = f a > > in (g foo, foo) > > > > Now, if f is expensive, *and g is not invertible*, then sharing foo might > be useful. It’s hard to think of a credible example, though. Regardless, > we should document it. > > > > Simon > > > > *From:* David Feuer <david.fe...@gmail.com> > *Sent:* 11 October 2019 17:03 > *To:* Simon Peyton Jones <simo...@microsoft.com> > *Cc:* ghc-devs <ghc-devs@haskell.org> > *Subject:* Re: atomicModifyMutVar2 > > > > On Fri, Oct 11, 2019, 11:08 AM Simon Peyton Jones <simo...@microsoft.com> > wrote: > > David > > I’m deeply puzzled atomicModifyMutVar2#. I have read the proposal > <https://nam06.safelinks.protection.outlook.com/?url=https%3A%2F%2Fgithub.com%2Fghc-proposals%2Fghc-proposals%2Fblob%2Fmaster%2Fproposals%2F0149-atomicModifyMutVar.rst&data=02%7C01%7Csimonpj%40microsoft.com%7C0b9a79c810d7453ce16008d74e9ebfc1%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C637064316038353079&sdata=LGyYiZC9b9g3lZpzTdvQgyEwKCaEsIzFDBcacVE2N5M%3D&reserved=0>, > and the comments in primops.txt.pp (reproduced below). > Question 1 > > I think the “real” type of atomicModifyMutVar2 is > > atomicModifyMutVar2# :: MutVar# s a > > -> (a -> (a,b)) > > -> State# s > > -> (# State# s, a, (a, b) #) > > > > Close, but not quite. The result doesn't have to be a pair. It can be a > tuple of any size at all. Indeed, it can even be an arbitrary record type > whose first pointer field has the appropriate type. > > > > Nowhere is this explicitly stated, but I believe that the intended > semantics of a call > > case (atomicModifyMutVar2# mv f s) of (# s’, x, r #) -> blah > > Then, suppose the old value of the MutVar was ‘*old’* > > - The primop builds a thunk *t *= *f old* > - The new value of the mutable variable is *(fst t)* > - The result *r* is t > - The result *x* is *old* > > Question: is that correct? We should state it explicitly. > > Yes, that sounds right. > > Question 2 > > Next question: Why does f have to return a pair? So far as I can tell, > it’s only so that a client can force it. The ‘b’ part never seems to play > a useful role. So we could equally well have had > > atomicModifyMutVar2# :: MutVar# s a > > -> (a -> Box a) > > -> State# s > > -> (# State# s, a, Unit a #) > > where Unit is defined in Data.Tuple > > data Unit a = Unit a > > Now you can force the result of (f old), just as with a pair. But the ‘b’ > would no longer complicate matters. > > Question: is the ‘b’ in the pair significant? Or could we use Unit? > > Yes, it's somewhat significant. You actually can use Unit with the new > primop (it's a tuple of arity 1), so that option is free. But using a pair > gets you a bit more: you can build a thunk that's *shared* between the > value installed in the MutVar and the one returned to the outside. Consider > > > > atomicModifyMutVar2# mv $ \a -> > > let foo = expensive_computation a > > in ([3,foo], foo) > > Question 3 > > In the comments below you say "but we don't know about pairs here”. Are > you sure? What stops you importing Data.Tuple into GHC.Prim? This fancy > footwork is one more complication, if it could be avoided. > > That whole regime came before my time, but since we win a bit by *not* > fixing it, o wouldn't jump on it too quick. > > > >
_______________________________________________ ghc-devs mailing list ghc-devs@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/ghc-devs