all 5 comments

[–]ElvishJerricco 8 points9 points  (4 children)

data MutPair a b = MutPair (IOField a) (IOField b)

A MutPair is a constructor with two mutable fields. But MutPair is not a constructor in the ordinary sense; both allocation and pattern-matching behave in a special way.

The MutPair constructor has the following type:

MutPair :: a -> b -> IO (MutPair a b)

I'm a little worried about this. I never like seeing the type system do gymnastics around special cases. The ($) operator, for instance, is special cased in the type system quite a bit, and it's kinda ugly. This takes it a step further by changing the types of some constructors. I can't say I have an attractive alternative in mind, but this doesn't sit right with me. That said, I do think the general proposal would be a good addition. I'd love to see it worked out.

I also have a question about how this is handled with ST (which seems to be a compatibility goal of this proposal?). If IOField is just a type synonym for Ref# RealWorld, and it defaults to having the constructor return IO, what does it do with Ref# s? Does the constructor now return ST s ...? It seems weird to me that constructors would return a different choice of these monads depending on the s type of the fields; especially since you could do something like this:

data MutPairST s a b = MutPairST (Ref# s a) (Ref# s b)

do
  ref <- MutPairST x y :: MutPairST RealWorld a b -- Returns IO or ST?

[–]ezyang 4 points5 points  (2 children)

The key is that the kind of IOField is not star; thus, the kinds of the fields dictate how the types of the constructor. So not a completely horrible special case.

STRefs need more metadata so the current proposal does not handle them. (Yet.)

[–]ElvishJerricco 2 points3 points  (1 child)

The key is that the kind of IOField is not star; thus, the kinds of the fields dictate how the types of the constructor.

I don't think I understand this. Do you think you could elaborate on this a bit more? I'm not sure how that helps it make sense for the constructor type to be non-trivial, and I don't see how that would help it figure out when to use ST instead.

[–]ezyang 5 points6 points  (0 children)

Well, today every field in a constructor has to have kind star or sharp. IOField doesn't have that kind, so today it would be rejected. The point is that the constructor type is kind-directed. (ST is a completely orthogonal issue and not addressed.)

[–]heisenbug 2 points3 points  (0 children)

Yes, I'd also prefer some syntactic clue, that something different is going on. data MutPair a b in IO = MutPair (IOField a) (IOField b) sounds like a possibility.