{-# LANGUAGE DefaultSignatures #-} {-# LANGUAGE EmptyCase #-} {-# LANGUAGE FlexibleContexts #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE FunctionalDependencies #-} {-# LANGUAGE GADTs #-} {-# LANGUAGE LambdaCase #-} {-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE RankNTypes #-} {-# LANGUAGE ScopedTypeVariables #-} {-# LANGUAGE StandaloneDeriving #-} {-# LANGUAGE TypeFamilyDependencies #-} {-# LANGUAGE TypeInType #-} {-# LANGUAGE TypeOperators #-} {-# LANGUAGE UndecidableInstances #-} module Data.Mutable.Internal ( Mutable(..) , RefFor(..) , DefaultMutable(..) -- * Instances -- ** Generic , GRef(..) , gThawRef, gFreezeRef , gCopyRef, gMoveRef, gCloneRef , gUnsafeThawRef, gUnsafeFreezeRef , GMutable (GRef_) -- ** Higher-Kinded Data Pattern , thawHKD, freezeHKD , copyHKD, moveHKD, cloneHKD , unsafeThawHKD, unsafeFreezeHKD -- ** Coercible , CoerceRef(..) , thawCoerce, freezeCoerce , copyCoerce, moveCoerce, cloneCoerce , unsafeThawCoerce, unsafeFreezeCoerce -- ** Traversable , TraverseRef(..) , thawTraverse, freezeTraverse , copyTraverse, moveTraverse, cloneTraverse , unsafeThawTraverse, unsafeFreezeTraverse -- ** Immutable , ImmutableRef(..), thawImmutable, freezeImmutable, copyImmutable -- ** Instances for Generics combinators themselves , GMutableRef(..) , MutSumF(..) ) where import Control.Monad.Primitive import Control.Monad.Trans.Class import Control.Monad.Trans.State import Data.Bifunctor import Data.Coerce import Data.Foldable import Data.Kind import Data.List import Data.Primitive.MutVar import Data.Vinyl.Functor import GHC.Generics import qualified Data.Vinyl.XRec as X -- | An instance of @'Mutable' m a@ means that @a@ can be stored -- a mutable reference in monad @m@. -- -- The associated type @'Ref' m a@ links any @a@ to the type of its -- canonical mutable version. -- -- The /benefit/ of this typeclass, instead of just using -- 'Data.IORef.IORef' or 'MutVar' or specific mutable versions like -- 'V.Vector' and 'MV.MVector', is two-fold: -- -- * Piecewise-mutable values, so you can write to only one part and not -- others. This also allows for cheaper "writes", even if you replace -- the whole value: you don't need to ever synthesize an entire new -- value, you can keep each component in a separate variable until you -- 'freezeRef' it out. This can be especially useful for composite -- data types containing large structures like 'V.Vector'. -- * Generic abstractions (similar to 'Show'), so you can automatically -- derive instances while preserving piecewise-ness. For example, the -- instance -- -- @ -- instance (Mutable m a, Mutable m b) => Mutable m (a, b) -- @ -- -- If @a@ and @b@ are piecwise-mutable, then the instance here will -- appropriately utilize that fact. -- -- To modify the specific parts of mutable values, it can be useful to use -- the functions in "Data.Mutable.Parts". -- -- There are facilities to automatically piecewise mutable versions for -- user-defined instances of 'Generic'. -- -- For example, if we have a type like: -- -- @ -- data TwoVectors = TV -- { tvInt :: 'V.Vector' Int -- , tvDouble :: Vector Double -- } -- deriving Generic -- -- instance Mutable m TwoVectors where -- type Ref m TwoVectors = 'GRef' m TwoVectors -- @ -- -- Then now we get: -- -- @ -- 'thawRef' :: TwoVectors -> m ('GRef' m TwoVectors) -- 'freezeRef' :: 'GRef' m TwoVectors -> m TwoVectors -- @ -- -- And @'GRef' m TwoVectors@ is now a piecewise-mutable reference storing each -- part in a way that can be modified separately (for example, with tools -- from "Data.Mutable.Parts"). It does this by internally allocating two -- 'MV.MVector's. If the two vectors are large, this can be much more -- efficient to modify (if you are modifying /several times/) than by just -- doing alterations on @TwoVector@s. It is also much better for large -- vectors if you plan on modifying only a single item in the vector. -- -- If you are using the "higher-kinded" data pattern, a la -- , then we -- can also do: -- -- @ -- data TwoVectors f = TV -- { tvInt :: 'X.HKD' f ('V.Vector' Int) -- , tvDouble :: HKD f (Vector Double) -- } -- deriving Generic -- -- instance Mutable (TwoVectors 'Identity') where -- type Ref (TwoVectors 'Identity') = TwoVectors ('RefFor' m) -- @ -- -- And now your mutable ref is literally going to be a product of the -- components -- -- @ -- ghci> tvr@(TV is ds) <- thawRef (TV xs ys) -- ghci> :t tvr -- TV ('RefFor' IO) -- ghci> :t is -- 'MV.MVector' RealWorld Int -- ghci> :t ds -- 'MV.MVector' RealWorld Double -- @ -- -- So 'thawRef' will actually just get you the same record type but with -- the mutable versions of each field. If you modify the mutable fields, -- and then later 'freezeRef' the whole thing, the resulting frozen value -- will incorporate all of the changes to the individual fields. -- -- In addition, there are a few more "automatically derived" instances you -- can get by picking 'Ref': -- -- @ -- -- Make a mutable version for any newtype wrapper, using the 'Mutable' -- -- of the underlying type -- newtype MyType = MT (Vector Double) -- -- type Ref m MyType = CoerceRef m MyType (Vector Double) -- -- -- Make a mutable version of any container, where the items are all -- -- mutable references. -- data MyContainer a = MC a a a a -- deriving (Functor, Foldable, Traversable) -- -- type Ref m (MyContainer a) = TraverseRef m MyContainer a -- @ -- -- See for more -- information on this typeclass and how to define instances -- automatically. class Monad m => Mutable m a where -- | Links the type @a@ to the type of its canonical "mutable version". -- -- For example, for 'V.Vector', the mutable version is 'MV.MVector', so -- we have -- -- @ -- type Ref m ('V.Vector' a) = 'MV.MVector' ('PrimState' m) a -- @ -- -- This means that using 'thawRef' on a 'V.Vector' will give you an -- 'MV.MVector', using 'freezeRef' on a 'MV.Vector' will give you -- a 'V.Vector', etc. -- -- @ -- 'thawRef' -- :: ('PrimMonad' m, s ~ 'PrimState' m) -- => 'V.Vector' a -- -> m ('MV.Vector' s a) -- -- 'freezeRef' -- :: ('PrimMonad' m, s ~ 'PrimState' m) -- => 'MV.Vector' s a -- -> m ('V.Vector' a) -- -- 'copyRef' -- :: ('PrimMonad' m, s ~ 'PrimState' m) -- => 'MV.Vector' s a -- -> 'V.Vector' a -- -> m () -- @ -- -- This associated type must be unique for @a@, so no two types @a@ can -- have the same @'Ref' m a@. This makes type inference a lot more -- useful: if you use 'freezeRef' on an 'MV.MVector', for instance, the -- return type will be inferred to be 'V.Vector'. -- -- The /default/ instance is just a plain old 'MutVar' containing the -- type. This is a valid instance, but it treats the entire type -- "wholesale" --- it is basically using it as a non-mutable type. You -- won't get any of the performance benefits of piecewise mutation from -- it, but it is useful as a base case for non-composite types like -- 'Int'. -- -- There are some built-in alternative options for user-defined ADTs -- with 'Generic' instances: -- -- @ -- -- Works for all 'Generic' instances, preserves piecewise mutation -- -- for products -- type Ref m a = 'GRef' m a -- @ -- -- If you just set up a blank instance, the implementations of -- 'thawRef', 'freezeRef', and 'copyRef' will be inferred using -- 'DefaultMutable'. -- -- @ -- data MyType -- -- -- The default setup is OK -- instance Mutable m MyType -- -- -- This is equivalent to the above -- instance Mutable m MyType -- type Ref m MyType = 'MutVar' ('PrimState' m) MyType -- -- -- any 'Generic' instance -- data MyType = MyType { mtInt :: Int, mtDouble :: Double } -- deriving Generic -- -- instance Mutable m MyType where -- type Ref m MyType = 'GRef' m MyType -- @ -- -- See for more -- information on this type family and how to define instances -- automatically. type Ref m a = (v :: Type) | v -> a type Ref m a = MutVar (PrimState m) a -- | "Thaw" a pure/persistent value into its mutable version, which can -- be manipulated using 'Data.Mutable.modifyRef' or other methods -- specific for that type (like 'MV.read'). -- -- Returns the 'Ref' instance, so, for example, for 'V.Vector': -- -- @ -- 'thawRef' -- :: ('PrimMonad' m, s ~ 'PrimState' m) -- => 'V.Vector' a -- -> m ('MV.Vector' s a) -- @ -- -- For non-composite (like 'Int'), this is often called the "new var" -- function, like 'Data.IORef.newIORef' / 'Data.STRef.newSTRef' -- / 'newMutVar' etc. thawRef :: a -> m (Ref m a) -- | "Freeze" a mutable value into its pure/persistent version. -- -- Takes a 'Ref' instance, but type inference will be able to infer the -- pure value's type because 'Ref' is injective. -- -- For example, for 'V.Vector': -- -- @ -- 'freezeRef' -- :: ('PrimMonad' m, s ~ 'PrimState' m) -- => 'MV.Vector' s a -- -> m ('V.Vector' a) -- @ -- -- For non-composite (like 'Int'), this is often called the "read var" -- function, like 'Data.IORef.readIORef' / 'Data.STRef.readSTRef' -- / 'readMutVar' etc. freezeRef :: Ref m a -> m a -- | Overwrite a mutable value by provivding a pure/persistent value. -- 'copyRef' -- -- Returns the 'Ref' and the value, so, for example, for 'V.Vector': -- -- @ -- 'copyRef' -- :: ('PrimMonad' m, s ~ 'PrimState' m) -- => 'MV.Vector' s a -- -> 'V.Vector' a -- -> m () -- @ -- -- Note that if @a@ is a composite type (with an appropriate composite -- reference), this will be done "piecewise": it'll write to each -- mutable component separately. -- -- For non-composite (like 'Int'), this is often called the "write var" -- function, like 'Data.IORef.writeIORef' / 'Data.STRef.writeSTRef' -- / 'writeMutVar' etc. copyRef :: Ref m a -- ^ destination to overwrite -> a -- ^ value -> m () -- | Deep Copy-move a mutable reference on top of another, overwriting the -- second one. -- -- For non-composite types, this is the same as a 'thawRef' and -- a 'copyRef'. For composite types this can be more effficient -- because the copying is done piecewise, so the intermediate pure value -- is never created. moveRef :: Ref m a -- ^ destination -> Ref m a -- ^ source -> m () -- | Create a deep copy of a mutable reference, allocated to a separate -- independent reference. -- -- For non-composite types, this is the same as a 'thawRef' and -- a 'freezeRef'. For composite types this can be more effficient -- because the cloning is done piecewise, so the intermediate pure value -- is never created. cloneRef :: Ref m a -> m (Ref m a) -- this is nice but you can't write an instance for 'TraverseRef' on -- this, so maybe not. -- -- | Initialize a mutable reference with fields being undefined or -- -- with undefined values. This is only useful if you can modify parts -- -- of the mutable value (with things like "Data.Mutable.Parts"). If -- -- you attempt to 'freezeRef' (or 'modifyRef' etc.) this before setting -- -- all of the fields to reasonable values, this is likely to blow up. -- initRef :: m (Ref m a) -- | A non-copying version of 'thawRef' that can be more efficient for -- types where the mutable representation is the same as the immutable -- one (like 'V.Vector'). -- -- This is safe as long as you never again use the original pure -- value, since it can potentially directly mutate it. unsafeThawRef :: a -> m (Ref m a) -- | A non-copying version of 'freezeRef' that can be more efficient for -- types where the mutable representation is the same as the immutable -- one (like 'V.Vector'). -- -- This is safe as long as you never again modify the mutable -- reference, since it can potentially directly mutate the frozen value -- magically. unsafeFreezeRef :: Ref m a -> m a default thawRef :: DefaultMutable m a (Ref m a) => a -> m (Ref m a) thawRef = defaultThawRef default freezeRef :: DefaultMutable m a (Ref m a) => Ref m a -> m a freezeRef = defaultFreezeRef default copyRef :: DefaultMutable m a (Ref m a) => Ref m a -> a -> m () copyRef = defaultCopyRef default moveRef :: DefaultMutable m a (Ref m a) => Ref m a -> Ref m a -> m () moveRef = defaultMoveRef default cloneRef :: DefaultMutable m a (Ref m a) => Ref m a -> m (Ref m a) cloneRef = defaultCloneRef default unsafeThawRef :: DefaultMutable m a (Ref m a) => a -> m (Ref m a) unsafeThawRef = defaultUnsafeThawRef default unsafeFreezeRef :: DefaultMutable m a (Ref m a) => Ref m a -> m a unsafeFreezeRef = defaultUnsafeFreezeRef -- | The default implementations of 'thawRef', 'freezeRef', and 'copyRef' -- dispatched for different choices of 'Ref'. -- -- Basically, by specifying 'Ref', you get the rest of the instance for -- free. -- -- We have the default case: -- -- @ -- -- default, if you don't specify 'Ref' -- instance Mutable m MyType -- -- -- the above is the same as: -- instance Mutable m MyType -- type Ref m MyType = MutVar (PrimState m) MyType -- @ -- -- The case for any instance of 'Generic': -- -- @ -- instance Mutable m MyType -- type Ref m MyType = GRef m MyType -- @ -- -- The case for the "higher-kinded data" pattern a la -- : -- -- @ -- instance Mutable m (MyTypeF Identity) -- type Ref m (MyTypeF Identity) = MyTypeF (RefFor m) -- @ -- -- The case for any newtype wrapper: -- -- @ -- newtype MyType = MT (Vector Double) -- -- instance Mutable m MyType where -- type Ref m MyType = CoerceRef m MyType (Vector Double) -- @ -- -- And the case for any 'Traversable instance, where the items will all be -- mutable references: -- -- @ -- data MyContainer a = MC a a a a -- deriving (Functor, Foldable, Traversable) -- -- instance Mutable m a => Mutable m (MyContainer a) where -- type Ref m (MyContainer a) = TraverseRef m MyContainer a -- @ -- class DefaultMutable m a r | r -> a where defaultThawRef :: a -> m r defaultFreezeRef :: r -> m a defaultCopyRef :: r -> a -> m () defaultMoveRef :: r -> r -> m () defaultCloneRef :: r -> m r defaultUnsafeThawRef :: a -> m r defaultUnsafeFreezeRef :: r -> m a instance (PrimMonad m, s ~ PrimState m) => DefaultMutable m a (MutVar s a) where defaultThawRef = newMutVar defaultFreezeRef = readMutVar defaultCopyRef = writeMutVar defaultMoveRef v u = writeMutVar v =<< readMutVar u defaultCloneRef v = newMutVar =<< readMutVar v defaultUnsafeThawRef = newMutVar defaultUnsafeFreezeRef = readMutVar instance (Generic a, GMutable m (Rep a)) => DefaultMutable m a (GRef m a) where defaultThawRef = gThawRef defaultFreezeRef = gFreezeRef defaultCopyRef = gCopyRef defaultMoveRef = gMoveRef defaultCloneRef = gCloneRef defaultUnsafeThawRef = gUnsafeThawRef defaultUnsafeFreezeRef = gUnsafeFreezeRef instance (Generic (z Identity), Generic (z (RefFor m)), GMutable m (Rep (z Identity)), GRef_ m (Rep (z Identity)) ~ Rep (z (RefFor m))) => DefaultMutable m (z Identity) (z (RefFor m)) where defaultThawRef = thawHKD defaultFreezeRef = freezeHKD defaultCopyRef = copyHKD defaultMoveRef = moveHKD defaultCloneRef = cloneHKD defaultUnsafeThawRef = unsafeThawHKD defaultUnsafeFreezeRef = unsafeFreezeHKD instance (Traversable f, Mutable m a) => DefaultMutable m (f a) (TraverseRef m f a) where defaultThawRef = thawTraverse defaultFreezeRef = freezeTraverse defaultCopyRef = copyTraverse defaultMoveRef = moveTraverse defaultCloneRef = cloneTraverse defaultUnsafeThawRef = unsafeThawTraverse defaultUnsafeFreezeRef = unsafeFreezeTraverse instance (Coercible s a, Mutable m a) => DefaultMutable m s (CoerceRef m s a) where defaultThawRef = thawCoerce defaultFreezeRef = freezeCoerce defaultCopyRef = copyCoerce defaultMoveRef = moveCoerce defaultCloneRef = cloneCoerce defaultUnsafeThawRef = unsafeThawCoerce defaultUnsafeFreezeRef = unsafeFreezeCoerce instance Applicative m => DefaultMutable m a (ImmutableRef a) where defaultThawRef = thawImmutable defaultFreezeRef = freezeImmutable defaultCopyRef = copyImmutable defaultMoveRef = moveImmutable defaultCloneRef = cloneImmutable defaultUnsafeThawRef = thawImmutable defaultUnsafeFreezeRef = freezeImmutable -- | A handy newtype wrapper that allows you to partially apply 'Ref'. -- @'RefFor' m a@ is the same as @'Ref' m a@, but can be partially applied. -- -- If used with 'X.HKD', you can treat this syntactically identically as -- a @'Ref' m a@. newtype RefFor m a = RefFor { getRefFor :: Ref m a } deriving instance Eq (Ref m a) => Eq (RefFor m a) deriving instance Ord (Ref m a) => Ord (RefFor m a) -- | Use a @'RefFor' m a@ as if it were a @'Ref' m a@. instance X.IsoHKD (RefFor m) a where type HKD (RefFor m) a = Ref m a unHKD = RefFor toHKD = getRefFor -- | A 'Ref' that works for any instance of 'Traversable', by using the -- fields of the 'Traversable' instance to /purely/ store mutable references. -- -- Note that this really only makes complete sense if the 'Traversable' is -- fixed-size, or you never modify the length of the traversable as you use -- it as a reference. -- -- If you /do/ modify the length, copying and modifying semantics can be -- a bit funky: -- -- * If copying a shorter item into a longer item ref, the "leftovers" items -- in the longer item are unchanged. -- * If copying a longer item into a shorter item ref, the leftover items -- are unchanged. -- -- @ -- ghci> r <- 'thawTraverse' [1..10] -- ghci> 'copyTraverse' r [0,0,0,0] -- ghci> 'freezeTraverse' r -- [0,0,0,0,5,6,7,8,9,10] -- ghci> 'copyTraverse' r [20..50] -- ghci> 'freezeTraverse' r -- [20,21,22,23,24,25,26,27,28,29] -- @ -- newtype TraverseRef m f a = TraverseRef { getTraverseRef :: f (Ref m a) } -- | Use a @'TraverseRef' m f a@ as if it were a @f ('Ref' m a)@ instance X.IsoHKD (TraverseRef m f) a where type HKD (TraverseRef m f) a = f (Ref m a) unHKD = TraverseRef toHKD = getTraverseRef -- | Default 'thawRef' for 'TraverseRef'. -- -- You likely won't ever use this directly, since it is automatically -- provided if you have a 'Mutable' instance with 'TraverseRef' as the -- 'Ref'. However, it can be useful if you are using a @'TraverseRef' -- m f a@ just as a normal data type, independent of the 'Ref' class. See -- documentation for 'TraverseRef' for more information. thawTraverse :: (Traversable f, Mutable m a) => f a -> m (TraverseRef m f a) thawTraverse = fmap TraverseRef . traverse thawRef -- | Default 'freezeRef' for 'TraverseRef'. -- -- You likely won't ever use this directly, since it is automatically -- provided if you have a 'Mutable' instance with 'TraverseRef' as the -- 'Ref'. However, it can be useful if you are using a @'TraverseRef' -- m f a@ just as a normal data type, independent of the 'Ref' class. See -- documentation for 'TraverseRef' for more information. freezeTraverse :: (Traversable f, Mutable m a) => TraverseRef m f a -> m (f a) freezeTraverse = traverse freezeRef . getTraverseRef -- | Default 'copyRef' for 'TraverseRef'. -- -- You likely won't ever use this directly, since it is automatically -- provided if you have a 'Mutable' instance with 'TraverseRef' as the -- 'Ref'. However, it can be useful if you are using a @'TraverseRef' -- m f a@ just as a normal data type, independent of the 'Ref' class. See -- documentation for 'TraverseRef' for more information. copyTraverse :: (Traversable f, Mutable m a) => TraverseRef m f a -> f a -> m () copyTraverse (TraverseRef rs) xs = evalStateT (traverse_ go rs) (toList xs) where go r = do x <- state $ maybe (Nothing, []) (first Just) . uncons lift $ mapM_ (copyRef r) x -- | Default 'moveRef' for 'TraverseRef'. -- -- You likely won't ever use this directly, since it is automatically -- provided if you have a 'Mutable' instance with 'TraverseRef' as the -- 'Ref'. However, it can be useful if you are using a @'TraverseRef' -- m f a@ just as a normal data type, independent of the 'Ref' class. See -- documentation for 'TraverseRef' for more information. moveTraverse :: (Traversable f, Mutable m a) => TraverseRef m f a -- ^ destination -> TraverseRef m f a -- ^ source -> m () moveTraverse (TraverseRef rs) (TraverseRef vs) = evalStateT (traverse_ go rs) (toList vs) where go r = do x <- state $ maybe (Nothing, []) (first Just) . uncons lift $ mapM_ (moveRef r) x -- | Default 'cloneRef' for 'TraverseRef'. -- -- You likely won't ever use this directly, since it is automatically -- provided if you have a 'Mutable' instance with 'TraverseRef' as the -- 'Ref'. However, it can be useful if you are using a @'TraverseRef' -- m f a@ just as a normal data type, independent of the 'Ref' class. See -- documentation for 'TraverseRef' for more information. cloneTraverse :: (Traversable f, Mutable m a) => TraverseRef m f a -> m (TraverseRef m f a) cloneTraverse = fmap TraverseRef . traverse cloneRef . getTraverseRef -- | Default 'unsafeThawRef' for 'TraverseRef'. -- -- You likely won't ever use this directly, since it is automatically -- provided if you have a 'Mutable' instance with 'TraverseRef' as the -- 'Ref'. However, it can be useful if you are using a @'TraverseRef' -- m f a@ just as a normal data type, independent of the 'Ref' class. See -- documentation for 'TraverseRef' for more information. unsafeThawTraverse :: (Traversable f, Mutable m a) => f a -> m (TraverseRef m f a) unsafeThawTraverse = fmap TraverseRef . traverse unsafeThawRef -- | Default 'unsafeFreezeRef' for 'TraverseRef'. -- -- You likely won't ever use this directly, since it is automatically -- provided if you have a 'Mutable' instance with 'TraverseRef' as the -- 'Ref'. However, it can be useful if you are using a @'TraverseRef' -- m f a@ just as a normal data type, independent of the 'Ref' class. See -- documentation for 'TraverseRef' for more information. unsafeFreezeTraverse :: (Traversable f, Mutable m a) => TraverseRef m f a -> m (f a) unsafeFreezeTraverse = traverse unsafeFreezeRef . getTraverseRef -- | A 'Ref' that works by using the 'Mutable' instance of an equivalent -- type. This is useful for newtype wrappers, so you can use the -- underlying data type's 'Mutable' instance. -- -- @ -- newtype MyVec = MyVec ('V.Vector' Double) -- -- instance 'Mutable' m MyVec where -- type 'Ref' m MyVec = 'CoerceRef' m s ('V.Vector' Double) -- @ -- -- The @Ref m MyVec@ uses the a @'MV.MVector' Double@ under the hood. -- -- It's essentially a special case of 'GRef' for newtypes. newtype CoerceRef m s a = CoerceRef { getCoerceRef :: Ref m a } deriving instance Eq (Ref m a) => Eq (CoerceRef m s a) deriving instance Ord (Ref m a) => Ord (CoerceRef m s a) -- | Use a @'CoerceRef' m s a@ as if it were a @'Ref' m a@ instance X.IsoHKD (CoerceRef m s) a where type HKD (CoerceRef m s) a = Ref m a unHKD = CoerceRef toHKD = getCoerceRef -- | Default 'thawRef' for 'CoerceRef'. -- -- You likely won't ever use this directly, since it is automatically -- provided if you have a 'Mutable' instance with 'CoerceRef' as the 'Ref'. -- However, it can be useful if you are using a @'CoerceRef' m s a@ just as -- a normal data type, independent of the 'Ref' class. See documentation -- for 'CoerceRef' for more information. thawCoerce :: (Coercible s a, Mutable m a) => s -> m (CoerceRef m s a) thawCoerce = fmap CoerceRef . thawRef . coerce -- | Default 'freezeRef' for 'CoerceRef'. -- -- You likely won't ever use this directly, since it is automatically -- provided if you have a 'Mutable' instance with 'CoerceRef' as the 'Ref'. -- However, it can be useful if you are using a @'CoerceRef' m s a@ just as -- a normal data type, independent of the 'Ref' class. See documentation -- for 'CoerceRef' for more information. freezeCoerce :: (Coercible s a, Mutable m a) => CoerceRef m s a -> m s freezeCoerce = fmap coerce . freezeRef . getCoerceRef -- | Default 'copyRef' for 'CoerceRef'. -- -- You likely won't ever use this directly, since it is automatically -- provided if you have a 'Mutable' instance with 'CoerceRef' as the 'Ref'. -- However, it can be useful if you are using a @'CoerceRef' m s a@ just as -- a normal data type, independent of the 'Ref' class. See documentation -- for 'CoerceRef' for more information. copyCoerce :: (Coercible s a, Mutable m a) => CoerceRef m s a -> s -> m () copyCoerce (CoerceRef r) = copyRef r . coerce -- | Default 'moveRef' for 'CoerceRef'. -- -- You likely won't ever use this directly, since it is automatically -- provided if you have a 'Mutable' instance with 'CoerceRef' as the 'Ref'. -- However, it can be useful if you are using a @'CoerceRef' m s a@ just as -- a normal data type, independent of the 'Ref' class. See documentation -- for 'CoerceRef' for more information. moveCoerce :: Mutable m a => CoerceRef m s a -> CoerceRef m s a -> m () moveCoerce (CoerceRef r) (CoerceRef s) = moveRef r s -- | Default 'cloneRef' for 'CoerceRef'. -- -- You likely won't ever use this directly, since it is automatically -- provided if you have a 'Mutable' instance with 'CoerceRef' as the 'Ref'. -- However, it can be useful if you are using a @'CoerceRef' m s a@ just as -- a normal data type, independent of the 'Ref' class. See documentation -- for 'CoerceRef' for more information. cloneCoerce :: Mutable m a => CoerceRef m s a -> m (CoerceRef m s a) cloneCoerce = fmap CoerceRef . cloneRef . getCoerceRef -- | Default 'unsafeThawRef' for 'CoerceRef'. -- -- You likely won't ever use this directly, since it is automatically -- provided if you have a 'Mutable' instance with 'CoerceRef' as the 'Ref'. -- However, it can be useful if you are using a @'CoerceRef' m s a@ just as -- a normal data type, independent of the 'Ref' class. See documentation -- for 'CoerceRef' for more information. unsafeThawCoerce :: (Coercible s a, Mutable m a) => s -> m (CoerceRef m s a) unsafeThawCoerce = fmap CoerceRef . unsafeThawRef . coerce -- | Default 'unsafeFreezeRef' for 'CoerceRef'. -- -- You likely won't ever use this directly, since it is automatically -- provided if you have a 'Mutable' instance with 'CoerceRef' as the 'Ref'. -- However, it can be useful if you are using a @'CoerceRef' m s a@ just as -- a normal data type, independent of the 'Ref' class. See documentation -- for 'CoerceRef' for more information. unsafeFreezeCoerce :: (Coercible s a, Mutable m a) => CoerceRef m s a -> m s unsafeFreezeCoerce = fmap coerce . unsafeFreezeRef . getCoerceRef -- | A "'Ref'" that can be used to give a default 'Mutable' instance that -- is immutable. Nothing is allocated ever, all attempts to modify it will -- be ignored, and 'freezeRef' will just get the original thawed value. -- -- Really only exists to be used with 'Data.Mutable.Class.Immutable'. newtype ImmutableRef a = ImmutableRef { getImmutableRef :: a } -- | Use a @'ImmutableRef' a@ as if it were an @a@ instance X.IsoHKD ImmutableRef a where type HKD ImmutableRef a = a unHKD = ImmutableRef toHKD = getImmutableRef -- | Default 'thawRef' for 'ImmutableRef'. -- -- You likely won't ever use this directly, since it is automatically -- provided if you have a 'Mutable' instance with 'ImmutableRef' as the 'Ref'. -- However, it can be useful if you are using a @'ImmutableRef' m s a@ just as -- a normal data type, independent of the 'Ref' class. See documentation -- for 'ImmutableRef' for more information. thawImmutable :: Applicative m => a -> m (ImmutableRef a) thawImmutable = pure . ImmutableRef -- | Default 'freezeRef' for 'ImmutableRef'. This will always return the -- originally thawed value, ignoring all copies and writes. -- -- You likely won't ever use this directly, since it is automatically -- provided if you have a 'Mutable' instance with 'ImmutableRef' as the 'Ref'. -- However, it can be useful if you are using a @'ImmutableRef' m s a@ just as -- a normal data type, independent of the 'Ref' class. See documentation -- for 'ImmutableRef' for more information. freezeImmutable :: Applicative m => ImmutableRef a -> m a freezeImmutable = pure . getImmutableRef -- | Default 'copyRef' for 'ImmutableRef'. This is a no-op and does -- nothing, since freezing will always return the originally thawed value. -- -- You likely won't ever use this directly, since it is automatically -- provided if you have a 'Mutable' instance with 'ImmutableRef' as the 'Ref'. -- However, it can be useful if you are using a @'ImmutableRef' m s a@ just as -- a normal data type, independent of the 'Ref' class. See documentation -- for 'ImmutableRef' for more information. copyImmutable :: Applicative m => ImmutableRef a -> a -> m () copyImmutable _ _ = pure () -- | Default 'moveRef' for 'ImmutableRef'. This is a no-op and does -- nothing, since freezing will always return the originally thawed value. -- -- You likely won't ever use this directly, since it is automatically -- provided if you have a 'Mutable' instance with 'ImmutableRef' as the 'Ref'. -- However, it can be useful if you are using a @'ImmutableRef' m s a@ just as -- a normal data type, independent of the 'Ref' class. See documentation -- for 'ImmutableRef' for more information. moveImmutable :: Applicative m => ImmutableRef a -> ImmutableRef a -> m () moveImmutable _ _ = pure () -- | Default 'cloneRef' for 'ImmutableRef'. 'freezeRef' on this value will -- return the originally thawed value. -- -- You likely won't ever use this directly, since it is automatically -- provided if you have a 'Mutable' instance with 'ImmutableRef' as the 'Ref'. -- However, it can be useful if you are using a @'ImmutableRef' m s a@ just as -- a normal data type, independent of the 'Ref' class. See documentation -- for 'ImmutableRef' for more information. cloneImmutable :: Applicative m => ImmutableRef a -> m (ImmutableRef a) cloneImmutable = pure -- | Class for automatic generation of 'Ref' for 'Generic' instances. See -- 'GRef' for more information. class Monad m => GMutable m f where type GRef_ m f = (u :: k -> Type) | u -> f gThawRef_ :: f a -> m (GRef_ m f a) gFreezeRef_ :: GRef_ m f a -> m (f a) gCopyRef_ :: GRef_ m f a -> f a -> m () gMoveRef_ :: GRef_ m f a -> GRef_ m f a -> m () gCloneRef_ :: GRef_ m f a -> m (GRef_ m f a) gUnsafeThawRef_ :: f a -> m (GRef_ m f a) gUnsafeFreezeRef_ :: GRef_ m f a -> m (f a) instance Mutable m c => GMutable m (K1 i c) where type GRef_ m (K1 i c) = K1 i (Ref m c) gThawRef_ = fmap K1 . thawRef . unK1 gFreezeRef_ = fmap K1 . freezeRef . unK1 gCopyRef_ (K1 v) (K1 x) = copyRef v x gMoveRef_ (K1 v) (K1 u) = moveRef v u gCloneRef_ = fmap K1 . cloneRef . unK1 gUnsafeThawRef_ = fmap K1 . unsafeThawRef . unK1 gUnsafeFreezeRef_ = fmap K1 . unsafeFreezeRef . unK1 instance Monad m => GMutable m U1 where type GRef_ m U1 = U1 gThawRef_ _ = pure U1 gFreezeRef_ _ = pure U1 gCopyRef_ _ _ = pure () gMoveRef_ _ _ = pure () gCloneRef_ _ = pure U1 gUnsafeThawRef_ _ = pure U1 gUnsafeFreezeRef_ _ = pure U1 instance Monad m => GMutable m V1 where type GRef_ m V1 = V1 gThawRef_ = \case {} gFreezeRef_ = \case {} gCopyRef_ = \case {} gMoveRef_ = \case {} gCloneRef_ = \case {} gUnsafeThawRef_ = \case {} gUnsafeFreezeRef_ = \case {} instance (GMutable m f, GMutable m g) => GMutable m (f :*: g) where type GRef_ m (f :*: g) = GRef_ m f :*: GRef_ m g gThawRef_ (x :*: y) = (:*:) <$> gThawRef_ x <*> gThawRef_ y gFreezeRef_ (v :*: u) = (:*:) <$> gFreezeRef_ v <*> gFreezeRef_ u gCopyRef_ (v :*: u) (x :*: y) = gCopyRef_ v x *> gCopyRef_ u y gMoveRef_ (v :*: u) (v' :*: u') = gMoveRef_ v v' *> gMoveRef_ u u' gCloneRef_ (v :*: u) = (:*:) <$> gCloneRef_ v <*> gCloneRef_ u gUnsafeThawRef_ (x :*: y) = (:*:) <$> gUnsafeThawRef_ x <*> gUnsafeThawRef_ y gUnsafeFreezeRef_ (v :*: u) = (:*:) <$> gUnsafeFreezeRef_ v <*> gUnsafeFreezeRef_ u instance GMutable m f => GMutable m (M1 i c f) where type GRef_ m (M1 i c f) = M1 i c (GRef_ m f) gThawRef_ = fmap M1 . gThawRef_ . unM1 gFreezeRef_ = fmap M1 . gFreezeRef_ . unM1 gCopyRef_ (M1 v) (M1 x) = gCopyRef_ v x gMoveRef_ (M1 v) (M1 u) = gMoveRef_ v u gCloneRef_ (M1 v) = M1 <$> gCloneRef_ v gUnsafeThawRef_ = fmap M1 . gUnsafeThawRef_ . unM1 gUnsafeFreezeRef_ = fmap M1 . gUnsafeFreezeRef_ . unM1 -- | Wraps ':+:' in a mutable reference. Used internally to represent -- generic sum references. newtype MutSumF m f g a = MutSumF { getMutSumF :: MutVar (PrimState m) ((f :+: g) a) } instance (GMutable m f, GMutable m g, PrimMonad m) => GMutable m (f :+: g) where type GRef_ m (f :+: g) = MutSumF m (GRef_ m f) (GRef_ m g) -- MutVar (PrimState m) :.: (GRef_ m f :+: GRef_ m g) gThawRef_ = \case L1 x -> fmap MutSumF . newMutVar . L1 =<< gThawRef_ x R1 x -> fmap MutSumF . newMutVar . R1 =<< gThawRef_ x gFreezeRef_ (MutSumF r) = readMutVar r >>= \case L1 v -> L1 <$> gFreezeRef_ v R1 u -> R1 <$> gFreezeRef_ u gCopyRef_ (MutSumF r) xy = readMutVar r >>= \case L1 v -> case xy of L1 x -> gCopyRef_ v x R1 y -> writeMutVar r . R1 =<< gThawRef_ y R1 u -> case xy of L1 x -> writeMutVar r . L1 =<< gThawRef_ x R1 y -> gCopyRef_ u y gMoveRef_ (MutSumF u) (MutSumF v) = readMutVar v >>= \case L1 vl -> readMutVar u >>= \case L1 ul -> gMoveRef_ ul vl R1 _ -> writeMutVar u . L1 =<< gCloneRef_ vl R1 vr -> readMutVar u >>= \case L1 _ -> writeMutVar u . R1 =<< gCloneRef_ vr R1 ur -> gMoveRef_ ur vr gCloneRef_ (MutSumF v) = readMutVar v >>= \case L1 u -> fmap MutSumF . newMutVar . L1 =<< gCloneRef_ u R1 u -> fmap MutSumF . newMutVar . R1 =<< gCloneRef_ u gUnsafeThawRef_ = \case L1 x -> fmap MutSumF . newMutVar . L1 =<< gUnsafeThawRef_ x R1 x -> fmap MutSumF . newMutVar . R1 =<< gUnsafeThawRef_ x gUnsafeFreezeRef_ (MutSumF r) = readMutVar r >>= \case L1 v -> L1 <$> gUnsafeFreezeRef_ v R1 u -> R1 <$> gUnsafeFreezeRef_ u -- | A 'Ref' for instances of 'GMutable', which are the "GHC.Generics" -- combinators. newtype GMutableRef m f a = GMutableRef { getGMutableRef :: GRef_ m f a } deriving instance Eq (GRef_ m f a) => Eq (GMutableRef m f a) deriving instance Ord (GRef_ m f a) => Ord (GMutableRef m f a) thawGMutableRef :: GMutable m f => f a -> m (GMutableRef m f a) thawGMutableRef = fmap GMutableRef . gThawRef_ freezeGMutableRef :: GMutable m f => GMutableRef m f a -> m (f a) freezeGMutableRef = gFreezeRef_ . getGMutableRef copyGMutableRef :: GMutable m f => GMutableRef m f a -> f a -> m () copyGMutableRef (GMutableRef r) = gCopyRef_ r moveGMutableRef :: GMutable m f => GMutableRef m f a -> GMutableRef m f a -> m () moveGMutableRef (GMutableRef r) (GMutableRef s) = gMoveRef_ r s cloneGMutableRef :: GMutable m f => GMutableRef m f a -> m (GMutableRef m f a) cloneGMutableRef (GMutableRef r) = GMutableRef <$> gCloneRef_ r unsafeThawGMutableRef :: GMutable m f => f a -> m (GMutableRef m f a) unsafeThawGMutableRef = fmap GMutableRef . gUnsafeThawRef_ unsafeFreezeGMutableRef :: GMutable m f => GMutableRef m f a -> m (f a) unsafeFreezeGMutableRef = gUnsafeFreezeRef_ . getGMutableRef instance Mutable m c => Mutable m (K1 i c a) where type Ref m (K1 i c a) = GMutableRef m (K1 i c) a thawRef = thawGMutableRef freezeRef = freezeGMutableRef copyRef = copyGMutableRef moveRef = moveGMutableRef cloneRef = cloneGMutableRef unsafeThawRef = unsafeThawGMutableRef unsafeFreezeRef = unsafeFreezeGMutableRef instance Monad m => Mutable m (U1 a) where type Ref m (U1 a) = GMutableRef m U1 a thawRef = thawGMutableRef freezeRef = freezeGMutableRef copyRef = copyGMutableRef moveRef = moveGMutableRef cloneRef = cloneGMutableRef unsafeThawRef = unsafeThawGMutableRef unsafeFreezeRef = unsafeFreezeGMutableRef instance Monad m => Mutable m (V1 a) where type Ref m (V1 a) = GMutableRef m V1 a thawRef = thawGMutableRef freezeRef = freezeGMutableRef copyRef = copyGMutableRef moveRef = moveGMutableRef cloneRef = cloneGMutableRef unsafeThawRef = unsafeThawGMutableRef unsafeFreezeRef = unsafeFreezeGMutableRef instance (GMutable m f, GMutable m g) => Mutable m ((f :*: g) a) where type Ref m ((f :*: g) a) = GMutableRef m (f :*: g) a thawRef = thawGMutableRef freezeRef = freezeGMutableRef copyRef = copyGMutableRef moveRef = moveGMutableRef cloneRef = cloneGMutableRef unsafeThawRef = unsafeThawGMutableRef unsafeFreezeRef = unsafeFreezeGMutableRef instance (GMutable m f, GMutable m g, PrimMonad m) => Mutable m ((f :+: g) a) where type Ref m ((f :+: g) a) = GMutableRef m (f :+: g) a thawRef = thawGMutableRef freezeRef = freezeGMutableRef copyRef = copyGMutableRef moveRef = moveGMutableRef cloneRef = cloneGMutableRef unsafeThawRef = unsafeThawGMutableRef unsafeFreezeRef = unsafeFreezeGMutableRef -- | Automatically generate a piecewise mutable reference for any 'Generic' -- instance. -- -- @ -- -- | any 'Generic' instance -- data MyType = MyType { mtInt :: Int, mtDouble :: Double } -- deriving (Generic, Show) -- -- instance Mutable m MyType where -- type Ref m MyType = 'GRef' m MyType -- @ -- -- @ -- ghci> r <- 'thawRef' (MyType 3 4.5) -- ghci> 'freezeRef' r -- MyType 3 4.5 -- ghci> 'Data.Mutable.Parts.freezePart' ('Data.Mutable.Parts.fieldMut' #mtInt) r -- 3 -- ghci> 'Data.Mutable.Parts.copyPart' (fieldMut #mtDouble) 1.23 -- ghci> freezeRef r -- MyType 3 1.23 -- @ -- -- Note that this is basically just a bunch of tupled refs for a product -- type. For a sum type (with multiple constructors), an extra layer of -- indirection is added to account for the dynamically changable shape. -- -- See "Data.Mutable.Parts" and "Data.Mutable.Branches" for nice ways to -- inspect and mutate the internals of this type (as demonstrated above). -- -- If the facilities in those modules are not adequate, you can also -- manually crack open 'GRef' and work with the internals. Getting the -- /type/ of @'unGRef' \@MyType@ should allow you to navigate what is going -- on, if you are familiar with "GHC.Generics". However, ideally, you -- would never need to do this. newtype GRef m a = GRef { unGRef :: GRef_ m (Rep a) () } deriving instance Eq (GRef_ m (Rep a) ()) => Eq (GRef m a) deriving instance Ord (GRef_ m (Rep a) ()) => Ord (GRef m a) -- | Default 'thawRef' for 'GRef'. -- -- You likely won't ever use this directly, since it is automatically -- provided if you have a 'Mutable' instance with 'GRef' as the 'Ref'. -- However, it can be useful if you are using a @'GRef' m a@ just as -- a normal data type, independent of the 'Ref' class. See documentation -- for 'GRef' for more information. gThawRef :: (Generic a, GMutable m (Rep a)) => a -> m (GRef m a) gThawRef = fmap GRef . gThawRef_ . from -- | Default 'freezeRef' for 'GRef'. -- -- You likely won't ever use this directly, since it is automatically -- provided if you have a 'Mutable' instance with 'GRef' as the 'Ref'. -- However, it can be useful if you are using a @'GRef' m a@ just as -- a normal data type, independent of the 'Ref' class. See documentation -- for 'GRef' for more information. gFreezeRef :: (Generic a, GMutable m (Rep a)) => GRef m a -> m a gFreezeRef = fmap to . gFreezeRef_ . unGRef -- | Default 'copyRef' for 'GRef'. -- -- You likely won't ever use this directly, since it is automatically -- provided if you have a 'Mutable' instance with 'GRef' as the 'Ref'. -- However, it can be useful if you are using a @'GRef' m a@ just as -- a normal data type, independent of the 'Ref' class. See documentation -- for 'GRef' for more information. gCopyRef :: (Generic a, GMutable m (Rep a)) => GRef m a -> a -> m () gCopyRef (GRef v) x = gCopyRef_ v (from x) -- | Default 'moveRef' for 'GRef'. -- -- You likely won't ever use this directly, since it is automatically -- provided if you have a 'Mutable' instance with 'GRef' as the 'Ref'. -- However, it can be useful if you are using a @'GRef' m a@ just as -- a normal data type, independent of the 'Ref' class. See documentation -- for 'GRef' for more information. gMoveRef :: GMutable m (Rep a) => GRef m a -> GRef m a -> m () gMoveRef (GRef v) (GRef u) = gMoveRef_ v u -- | Default 'cloneRef' for 'GRef'. -- -- You likely won't ever use this directly, since it is automatically -- provided if you have a 'Mutable' instance with 'GRef' as the 'Ref'. -- However, it can be useful if you are using a @'GRef' m a@ just as -- a normal data type, independent of the 'Ref' class. See documentation -- for 'GRef' for more information. gCloneRef :: GMutable m (Rep a) => GRef m a -> m (GRef m a) gCloneRef (GRef v) = GRef <$> gCloneRef_ v -- | Default 'unsafeThawRef' for 'GRef'. -- -- You likely won't ever use this directly, since it is automatically -- provided if you have a 'Mutable' instance with 'GRef' as the 'Ref'. -- However, it can be useful if you are using a @'GRef' m a@ just as -- a normal data type, independent of the 'Ref' class. See documentation -- for 'GRef' for more information. gUnsafeThawRef :: (Generic a, GMutable m (Rep a)) => a -> m (GRef m a) gUnsafeThawRef = fmap GRef . gUnsafeThawRef_ . from -- | Default 'unsafeFreezeRef' for 'GRef'. -- -- You likely won't ever use this directly, since it is automatically -- provided if you have a 'Mutable' instance with 'GRef' as the 'Ref'. -- However, it can be useful if you are using a @'GRef' m a@ just as -- a normal data type, independent of the 'Ref' class. See documentation -- for 'GRef' for more information. gUnsafeFreezeRef :: (Generic a, GMutable m (Rep a)) => GRef m a -> m a gUnsafeFreezeRef = fmap to . gUnsafeFreezeRef_ . unGRef -- | Default 'thawRef' for the higher-kinded data pattern, a la -- . -- -- You likely won't ever use this directly, since it is automatically -- provided if you have a 'Mutable' instance with @z ('RefFor' m)@ as the 'Ref'. -- However, it can be useful if you are using a @z ('RefFor' m)@ just as -- a normal data type, independent of the 'Ref' class. See documentation -- for 'Mutable' for more information. thawHKD :: forall z m. ( Generic (z Identity) , Generic (z (RefFor m)) , GMutable m (Rep (z Identity)) , GRef_ m (Rep (z Identity)) ~ Rep (z (RefFor m)) ) => z Identity -> m (z (RefFor m)) thawHKD = fmap to . gThawRef_ . from -- | Default 'freezeRef' for the higher-kinded data pattern, a la -- . -- -- You likely won't ever use this directly, since it is automatically -- provided if you have a 'Mutable' instance with @z ('RefFor' m)@ as the 'Ref'. -- However, it can be useful if you are using a @z ('RefFor' m)@ just as -- a normal data type, independent of the 'Ref' class. See documentation -- for 'Mutable' for more information. freezeHKD :: forall z m. ( Generic (z Identity) , Generic (z (RefFor m)) , GMutable m (Rep (z Identity)) , GRef_ m (Rep (z Identity)) ~ Rep (z (RefFor m)) ) => z (RefFor m) -> m (z Identity) freezeHKD = fmap to . gFreezeRef_ . from -- | Default 'copyRef' for the higher-kinded data pattern, a la -- . -- -- You likely won't ever use this directly, since it is automatically -- provided if you have a 'Mutable' instance with @z ('RefFor' m)@ as the 'Ref'. -- However, it can be useful if you are using a @z ('RefFor' m)@ just as -- a normal data type, independent of the 'Ref' class. See documentation -- for 'Mutable' for more information. copyHKD :: forall z m. ( Generic (z Identity) , Generic (z (RefFor m)) , GMutable m (Rep (z Identity)) , GRef_ m (Rep (z Identity)) ~ Rep (z (RefFor m)) ) => z (RefFor m) -> z Identity -> m () copyHKD r x = gCopyRef_ (from r) (from x) -- | Default 'moveRef' for the higher-kinded data pattern, a la -- . -- -- You likely won't ever use this directly, since it is automatically -- provided if you have a 'Mutable' instance with @z ('RefFor' m)@ as the 'Ref'. -- However, it can be useful if you are using a @z ('RefFor' m)@ just as -- a normal data type, independent of the 'Ref' class. See documentation -- for 'Mutable' for more information. moveHKD :: forall z m. ( Generic (z (RefFor m)) , GMutable m (Rep (z Identity)) , GRef_ m (Rep (z Identity)) ~ Rep (z (RefFor m)) ) => z (RefFor m) -> z (RefFor m) -> m () moveHKD r x = gMoveRef_ (from r) (from x) -- | Default 'cloneRef' for the higher-kinded data pattern, a la -- . -- -- You likely won't ever use this directly, since it is automatically -- provided if you have a 'Mutable' instance with @z ('RefFor' m)@ as the 'Ref'. -- However, it can be useful if you are using a @z ('RefFor' m)@ just as -- a normal data type, independent of the 'Ref' class. See documentation -- for 'Mutable' for more information. cloneHKD :: forall z m. ( Generic (z (RefFor m)) , GMutable m (Rep (z Identity)) , GRef_ m (Rep (z Identity)) ~ Rep (z (RefFor m)) ) => z (RefFor m) -> m (z (RefFor m)) cloneHKD = fmap to . gCloneRef_ . from -- | Default 'unsafeThawRef' for the higher-kinded data pattern, a la -- . -- -- You likely won't ever use this directly, since it is automatically -- provided if you have a 'Mutable' instance with @z ('RefFor' m)@ as the 'Ref'. -- However, it can be useful if you are using a @z ('RefFor' m)@ just as -- a normal data type, independent of the 'Ref' class. See documentation -- for 'Mutable' for more information. unsafeThawHKD :: forall z m. ( Generic (z Identity) , Generic (z (RefFor m)) , GMutable m (Rep (z Identity)) , GRef_ m (Rep (z Identity)) ~ Rep (z (RefFor m)) ) => z Identity -> m (z (RefFor m)) unsafeThawHKD = fmap to . gUnsafeThawRef_ . from -- | Default 'unsafeFreezeRef' for the higher-kinded data pattern, a la -- . -- -- You likely won't ever use this directly, since it is automatically -- provided if you have a 'Mutable' instance with @z ('RefFor' m)@ as the 'Ref'. -- However, it can be useful if you are using a @z ('RefFor' m)@ just as -- a normal data type, independent of the 'Ref' class. See documentation -- for 'Mutable' for more information. unsafeFreezeHKD :: forall z m. ( Generic (z Identity) , Generic (z (RefFor m)) , GMutable m (Rep (z Identity)) , GRef_ m (Rep (z Identity)) ~ Rep (z (RefFor m)) ) => z (RefFor m) -> m (z Identity) unsafeFreezeHKD = fmap to . gUnsafeFreezeRef_ . from