Actually, maybe we can do better! We don't inherently need the function to be a selector. But to make it more general, we'll need to take some care to make sure to produce good code when it *is* a selector.
On Fri, Oct 11, 2019, 6:59 PM David Feuer <david.fe...@gmail.com> wrote: > 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%7C10950014fe9d46a6682508d74e649537%7C72f988bf86f141af91ab2d7cd011db47%7C1%7C0%7C637064066214164213&sdata=2phccb9r%2Fcg4xs7beKByn%2F1Ivxz7kvN5xkejhOpDfg8%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