id	summary	reporter	owner	description	type	status	priority	milestone	version	resolution	keywords	cc
83	PhaseChange class, Mutable data family	illissius		"Hello,

How receptive would you be towards a change to primitive and/or vector somewhere along the line of the following?

{{{
class PhaseChange a where
    data Mutable a :: * -> *
    unsafeThaw :: a -> ST s (Mutable a s)
    unsafeFreeze :: Mutable a s -> ST s a
    copy :: Mutable a s -> ST s (Mutable a s)

-- all of these ST s could be PrimMonad m (or MonadST m) instead
thaw :: PhaseChange a => a -> ST s (Mutable a s)
thaw = copy <=< unsafeThaw

freeze :: PhaseChange a => Mutable a s -> ST s a
freeze = unsafeFreeze <=< copy

...other functions, such as 'modify' from vector...

instance PhaseChange ByteArray where
    data Mutable ByteArray s = MutableByteArray (MutableByteArray# s)
    ...

type MutableByteArray = Mutable ByteArray

instance PhaseChange (Array a) where
    data Mutable (Array a) s = MutableArray (MutableArray# s a)
    ...

type MutableArray s a = Mutable (Array a) s

-- forall Vectors
instance PhaseChange (Vector a) where
    data Mutable (Vector a) s = MVector !(MutableArray s a) !Int !Int
    ...

type MVector s a = Mutable (Vector a) s
}}}

Advantages: There would be a uniform interface for interacting with types which can be converted between mutable and immutable forms, with operations available which can be defined purely in terms of it (such as 'modify'); the various Arrays and Vectors would implement it, but relevant third parties would also be able to.

Disadvantages: It would not be possible to partially apply the !MutableArray and MVector types. This would totally break the MVector class and the Mutable type family, which would have to be redesigned to accomodate (presumably using the new Mutable data family instead). To be honest I didn't realize this when I started writing, and I wouldn't be surprised if it's a deal breaker. An other possibility would be to have a separate !PhaseChange1 class for * -> * types, which I think would solve this problem, but didn't work so well when I last tried it for reasons I can't remember (albeit that was still with the MPTC formulation, see below).

Motivation: I have a phasechange package on Hackage[1], which implements the same concept as above except currently with an MPTC and TFs with bidirectional equality constraints (so, basically FDs). I realized that the whole thing would be a lot more simple and straightforward if instead of the whole TFs machinery I had a simple Mutable data family like above, but that would require instances to adapt to the class, instead of vice versa like now. Hence this ticket. If vector doesn't want to adapt then I would have to choose between the more appealing formulation and the Vector instances. If by chance it does want to adapt then I can work on preparing a patch. (Motivation for the phasechange package: I'm slowly working on bindings for Qt, and its various data types would be represented on the Haskell side in both mutable and immutable forms, which would implement this interface.)

[1] http://hackage.haskell.org/package/phasechange"	enhancement	new	minor					
