Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Instances for IORef/TVar/MVar and other mutable containers #6

Closed
bennofs opened this issue Apr 12, 2015 · 6 comments
Closed

Instances for IORef/TVar/MVar and other mutable containers #6

bennofs opened this issue Apr 12, 2015 · 6 comments

Comments

@bennofs
Copy link

bennofs commented Apr 12, 2015

I'd like to propose the following instances:

instance NFData (IORef a) where rnf x = seq x ()
instance NFData (TVar a) where rnf x = seq x ()
instance NFData (MVar a) where rnf x = seq x ()

I think forcing a mutable container should not force the contained value, since that is not really "part" of the data type, it is just referenced. The instances are nevertheless useful when working with APIs that expect NFData types, for example criterion.

@snoyberg
Copy link

Sounds reasonable to me.

@hvr hvr added this to the 1.4.2.0 milestone Apr 13, 2015
@ekmett
Copy link
Member

ekmett commented Apr 13, 2015

Makes sense to me.

Way down in the guts of STRef, (and IORef, which is just a newtype of STRef RealWorld) there is a MutVar# which is of kind #, but lives on the heap as its own special closure type. What I don't know is if the MutVar# itself can ever be lazy. I just know it has a special heap closure type that is used to hold onto it. That thing is where we actually bang in the pointers when we update the IORef/STRef.

STRef is basically a data box that carries around a reference to that MutVar#, and it delegates to the underlying MutVar# for its identity, etc.

My guess/assumption is that it is always strict, warranting the # kind, but it might be worth double checking with someone who can give a more authoritative answer, e.g. Simon Marlow.

@simonmar
Copy link
Member

Yes, it is always strict. These built-in types are unlifted (meaning they cannot be _|_).

@ekmett
Copy link
Member

ekmett commented Apr 14, 2015

Thanks. That'll help simplify the code I have for forcing all the way down to them in my not-yet-released discrimination package.

Longer verson:

In my case I have a [(IORef a,b)], so I first force the list all the way down to the IORefs and count the number of entries, then make a MutableByteArray# of the right length, and in a custom foreign prim I can gather the addresses by walking the now guaranteed to be forced list of pairs down to the IORef to get the MutVar# out and take their addresses and drop them into the MutableByteArray#. Since this prim never forces any thunks on the heap, it merely walks past indirections, etc. by hand and we know we've already forced everything, it gathers all of the addresses before the garbage collector can fire. Then I can do equivalence class partitioning on them in linear time.

Previously I was walking all the way down to the MutVar#, but if I can stop at the STRef constructor in the forcing pass it'll save a little bit of work.

Fritz Henglein wrote a couple of papers on this idea (among others) in a more general setting.

glguy added a commit that referenced this issue Oct 13, 2015
@glguy
Copy link
Member

glguy commented Oct 13, 2015

The above commit doesn't add the TVar instance because I wasn't able to import GHC.Conc safely. Is there a safe way to get this instance? Does the module need to become Trustworthy?

@hvr hvr added the instances label Apr 17, 2016
@hvr
Copy link
Member

hvr commented Apr 17, 2016

@glguy tbh, I don't like to sacrifice {-# LANGUAGE Safe #-} only because of one instance... I'll punt on TVar for 1.4.2;

maybe we could just have the stm package define an orphan NFData instance, after all stm is the recommended public STM api afaik.

maybe at some point in the future NFData will be folded into base... then it could become a non-orphan without the SafeHaskell issues...

@hvr hvr closed this as completed Apr 17, 2016
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

6 participants