-- Hoogle documentation, generated by Haddock -- See Hoogle, http://www.haskell.org/hoogle/ -- | Automatic piecewise-mutable references for your types -- -- Associate and generate "piecewise-mutable" versions for your composite -- data types. Think of it like a "generalized MVector for all ADTs". -- -- Useful for a situation where you have a record with many fields (or -- many nested records) that you want to use for efficient mutable -- in-place algorithms. This library lets you do efficient "piecewise" -- mutations (operations that only edit one field), and also efficient -- entire-datatype copies/updates, as well, in many cases. -- -- See https://mutable.jle.im for official introduction and -- documentation, or jump right in by importing Data.Mutable. @package mutable @version 0.2.2.0 -- | Exports Ref data types for various common data types, and also -- the tools for automatic derivation of instances. See -- Data.Mutable for more information. module Data.Mutable.Instances -- | Ref for components in a vinyl Rec. newtype RecRef s f a RecRef :: Ref s (f a) -> RecRef s f a [getRecRef] :: RecRef s f a -> Ref s (f a) -- | The mutable reference of the HList type from generic-lens. data HListRef :: Type -> [Type] -> Type [NilRef] :: HListRef s '[] [:!>] :: Ref s a -> HListRef s as -> HListRef s (a : as) infixr 5 :!> -- | The Ref for () (unit). This breaks the pattern for -- tuple instances (type Ref s (a, b) = (Ref s a, -- Ref s b)), but is necessary for type inference (see -- documentation for Ref). data UnitRef s UnitRef :: UnitRef s -- | The Ref for Void. data VoidRef s -- | 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 s MyType where
-- type Ref s MyType = GRef s MyType
--
--
-- -- ghci> r <- thawRef (MyType 3 4.5) -- ghci> freezeRef r -- MyType 3 4.5 -- ghci> freezePart (fieldMut #mtInt) r -- 3 -- ghci> 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 s a GRef :: GRef_ s (Rep a) () -> GRef s a [unGRef] :: GRef s a -> GRef_ s (Rep 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 s a just as a normal data type, independent of -- the Ref class. See documentation for GRef for more -- information. gThawRef :: (Generic a, GMutable s (Rep a), PrimMonad m, PrimState m ~ s) => a -> m (GRef s a) -- | 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 s a just as a normal data type, independent of -- the Ref class. See documentation for GRef for more -- information. gFreezeRef :: (Generic a, GMutable s (Rep a), PrimMonad m, PrimState m ~ s) => GRef s a -> m a -- | 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 s a just as a normal data type, independent of -- the Ref class. See documentation for GRef for more -- information. gCopyRef :: (Generic a, GMutable s (Rep a), PrimMonad m, PrimState m ~ s) => GRef s a -> a -> m () -- | 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 s a just as a normal data type, independent of -- the Ref class. See documentation for GRef for more -- information. gMoveRef :: (GMutable s (Rep a), PrimMonad m, PrimState m ~ s) => GRef s a -> GRef s a -> m () -- | 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 s a just as a normal data type, independent of -- the Ref class. See documentation for GRef for more -- information. gCloneRef :: (GMutable s (Rep a), PrimMonad m, PrimState m ~ s) => GRef s a -> m (GRef s a) -- | 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 s a just as a normal data type, independent of -- the Ref class. See documentation for GRef for more -- information. gUnsafeThawRef :: (Generic a, GMutable s (Rep a), PrimMonad m, PrimState m ~ s) => a -> m (GRef s a) -- | 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 s a just as a normal data type, independent of -- the Ref class. See documentation for GRef for more -- information. gUnsafeFreezeRef :: (Generic a, GMutable s (Rep a), PrimMonad m, PrimState m ~ s) => GRef s a -> m a -- | Class for automatic generation of Ref for Generic -- instances. See GRef for more information. class GMutable s (f :: Type -> Type) where { type family GRef_ s f = (u :: Type -> Type) | u -> f; } -- | Default thawRef for the higher-kinded data pattern, a la -- https://reasonablypolymorphic.com/blog/higher-kinded-data/. -- -- You likely won't ever use this directly, since it is automatically -- provided if you have a Mutable instance with z -- (RefFor s) as the Ref. However, it can be useful if -- you are using a z (RefFor s) just as a normal data -- type, independent of the Ref class. See documentation for -- Mutable for more information. thawHKD :: forall z m s. (Generic (z Identity), Generic (z (RefFor s)), GMutable s (Rep (z Identity)), GRef_ s (Rep (z Identity)) ~ Rep (z (RefFor s)), PrimMonad m, PrimState m ~ s) => z Identity -> m (z (RefFor s)) -- | Default freezeRef for the higher-kinded data pattern, a la -- https://reasonablypolymorphic.com/blog/higher-kinded-data/. -- -- You likely won't ever use this directly, since it is automatically -- provided if you have a Mutable instance with z -- (RefFor s) as the Ref. However, it can be useful if -- you are using a z (RefFor s) just as a normal data -- type, independent of the Ref class. See documentation for -- Mutable for more information. freezeHKD :: forall z m s. (Generic (z Identity), Generic (z (RefFor s)), GMutable s (Rep (z Identity)), GRef_ s (Rep (z Identity)) ~ Rep (z (RefFor s)), PrimMonad m, PrimState m ~ s) => z (RefFor s) -> m (z Identity) -- | Default copyRef for the higher-kinded data pattern, a la -- https://reasonablypolymorphic.com/blog/higher-kinded-data/. -- -- You likely won't ever use this directly, since it is automatically -- provided if you have a Mutable instance with z -- (RefFor s) as the Ref. However, it can be useful if -- you are using a z (RefFor s) just as a normal data -- type, independent of the Ref class. See documentation for -- Mutable for more information. copyHKD :: forall z m s. (Generic (z Identity), Generic (z (RefFor s)), GMutable s (Rep (z Identity)), GRef_ s (Rep (z Identity)) ~ Rep (z (RefFor s)), PrimMonad m, PrimState m ~ s) => z (RefFor s) -> z Identity -> m () -- | Default moveRef for the higher-kinded data pattern, a la -- https://reasonablypolymorphic.com/blog/higher-kinded-data/. -- -- You likely won't ever use this directly, since it is automatically -- provided if you have a Mutable instance with z -- (RefFor s) as the Ref. However, it can be useful if -- you are using a z (RefFor s) just as a normal data -- type, independent of the Ref class. See documentation for -- Mutable for more information. moveHKD :: forall z m s. (Generic (z (RefFor s)), GMutable s (Rep (z Identity)), GRef_ s (Rep (z Identity)) ~ Rep (z (RefFor s)), PrimMonad m, PrimState m ~ s) => z (RefFor s) -> z (RefFor s) -> m () -- | Default cloneRef for the higher-kinded data pattern, a la -- https://reasonablypolymorphic.com/blog/higher-kinded-data/. -- -- You likely won't ever use this directly, since it is automatically -- provided if you have a Mutable instance with z -- (RefFor s) as the Ref. However, it can be useful if -- you are using a z (RefFor s) just as a normal data -- type, independent of the Ref class. See documentation for -- Mutable for more information. cloneHKD :: forall z m s. (Generic (z (RefFor s)), GMutable s (Rep (z Identity)), GRef_ s (Rep (z Identity)) ~ Rep (z (RefFor s)), PrimMonad m, PrimState m ~ s) => z (RefFor s) -> m (z (RefFor s)) -- | Default unsafeThawRef for the higher-kinded data pattern, a la -- https://reasonablypolymorphic.com/blog/higher-kinded-data/. -- -- You likely won't ever use this directly, since it is automatically -- provided if you have a Mutable instance with z -- (RefFor s) as the Ref. However, it can be useful if -- you are using a z (RefFor s) just as a normal data -- type, independent of the Ref class. See documentation for -- Mutable for more information. unsafeThawHKD :: forall z m s. (Generic (z Identity), Generic (z (RefFor s)), GMutable s (Rep (z Identity)), GRef_ s (Rep (z Identity)) ~ Rep (z (RefFor s)), PrimMonad m, PrimState m ~ s) => z Identity -> m (z (RefFor s)) -- | Default unsafeFreezeRef for the higher-kinded data pattern, a -- la https://reasonablypolymorphic.com/blog/higher-kinded-data/. -- -- You likely won't ever use this directly, since it is automatically -- provided if you have a Mutable instance with z -- (RefFor s) as the Ref. However, it can be useful if -- you are using a z (RefFor s) just as a normal data -- type, independent of the Ref class. See documentation for -- Mutable for more information. unsafeFreezeHKD :: forall z m s. (Generic (z Identity), Generic (z (RefFor s)), GMutable s (Rep (z Identity)), GRef_ s (Rep (z Identity)) ~ Rep (z (RefFor s)), PrimMonad m, PrimState m ~ s) => z (RefFor s) -> m (z Identity) -- | 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 (Vector Double) -- -- instance Mutable s MyVec where -- type Ref s MyVec = CoerceRef s s (Vector Double) ---- -- The Ref s MyVec uses the a MVector Double -- under the hood. -- -- It's essentially a special case of GRef for newtypes. newtype CoerceRef s b a CoerceRef :: Ref s a -> CoerceRef s b a [getCoerceRef] :: CoerceRef s b a -> Ref s a -- | 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 s b a just as a normal data type, -- independent of the Ref class. See documentation for -- CoerceRef for more information. thawCoerce :: (Coercible b a, Mutable s a, PrimMonad m, PrimState m ~ s) => b -> m (CoerceRef s b a) -- | 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 s b a just as a normal data type, -- independent of the Ref class. See documentation for -- CoerceRef for more information. freezeCoerce :: (Coercible b a, Mutable s a, PrimMonad m, PrimState m ~ s) => CoerceRef s b a -> m b -- | 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 s b a just as a normal data type, -- independent of the Ref class. See documentation for -- CoerceRef for more information. copyCoerce :: (Coercible b a, Mutable s a, PrimMonad m, PrimState m ~ s) => CoerceRef s b a -> b -> m () -- | 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 s b a just as a normal data type, -- independent of the Ref class. See documentation for -- CoerceRef for more information. moveCoerce :: (Mutable s a, PrimMonad m, PrimState m ~ s) => CoerceRef s b a -> CoerceRef s b a -> m () -- | 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 s b a just as a normal data type, -- independent of the Ref class. See documentation for -- CoerceRef for more information. cloneCoerce :: (Mutable s a, PrimMonad m, PrimState m ~ s) => CoerceRef s b a -> m (CoerceRef s b a) -- | 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 s b a just as a normal data type, -- independent of the Ref class. See documentation for -- CoerceRef for more information. unsafeThawCoerce :: (Coercible b a, Mutable s a, PrimMonad m, PrimState m ~ s) => b -> m (CoerceRef s b a) -- | 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 s b a just as a normal data type, -- independent of the Ref class. See documentation for -- CoerceRef for more information. unsafeFreezeCoerce :: (Coercible b a, Mutable s a, PrimMonad m, PrimState m ~ s) => CoerceRef s b a -> m b -- | 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: -- --
-- 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 s f a TraverseRef :: f (Ref s a) -> TraverseRef s f a [getTraverseRef] :: TraverseRef s f a -> f (Ref s a) -- | 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 s a, PrimMonad m, PrimState m ~ s) => f a -> m (TraverseRef s f a) -- | 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 s a, PrimMonad m, PrimState m ~ s) => TraverseRef s f a -> m (f a) -- | 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 s a, PrimMonad m, PrimState m ~ s) => TraverseRef s f a -> f a -> m () -- | 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 s a, PrimMonad m, PrimState m ~ s) => TraverseRef s f a -> TraverseRef s f a -> m () -- | 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 s a, PrimMonad m, PrimState m ~ s) => TraverseRef s f a -> m (TraverseRef s f a) -- | 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 s a, PrimMonad m, PrimState m ~ s) => f a -> m (TraverseRef s f a) -- | 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 s a, PrimMonad m, PrimState m ~ s) => TraverseRef s f a -> m (f a) -- | 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 Immutable. newtype ImmutableRef s a ImmutableRef :: a -> ImmutableRef s a [getImmutableRef] :: ImmutableRef s a -> a -- | 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 s b 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 s a) -- | 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 s b a just as a normal -- data type, independent of the Ref class. See documentation for -- ImmutableRef for more information. freezeImmutable :: Applicative m => ImmutableRef s a -> m a -- | 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 s b a just as a normal -- data type, independent of the Ref class. See documentation for -- ImmutableRef for more information. copyImmutable :: Applicative m => ImmutableRef s a -> a -> m () -- | A Ref for instances of GMutable, which are the -- GHC.Generics combinators. newtype GMutableRef s f a GMutableRef :: GRef_ s f a -> GMutableRef s f a [getGMutableRef] :: GMutableRef s f a -> GRef_ s f a -- | Wraps :+: in a mutable reference. Used internally to represent -- generic sum references. newtype MutSumF s f g a MutSumF :: MutVar s ((f :+: g) a) -> MutSumF s f g a [getMutSumF] :: MutSumF s f g a -> MutVar s ((f :+: g) a) -- | Useful type family to Ref m over every item in a -- type-level list -- --
-- ghci> :kind! MapRef IO '[Int, V.Vector Double] -- '[ MutVar RealWorld Int, MVector RealWorld Double ] --type family MapRef s as instance (Data.Mutable.Internal.Ref s a GHC.Types.~ ra, Data.Mutable.Internal.Ref s b GHC.Types.~ rb, Data.Mutable.Internal.Ref s c GHC.Types.~ rc) => Data.Mutable.Internal.ListRefTuple s (ra, rb, rc) '[a, b, c] instance (Data.Mutable.Internal.Ref s a GHC.Types.~ ra, Data.Mutable.Internal.Ref s b GHC.Types.~ rb, Data.Mutable.Internal.Ref s c GHC.Types.~ rc, Data.Mutable.Internal.Ref s d GHC.Types.~ rd) => Data.Mutable.Internal.ListRefTuple s (ra, rb, rc, rd) '[a, b, c, d] instance (Data.Mutable.Internal.Ref s a GHC.Types.~ ra, Data.Mutable.Internal.Ref s b GHC.Types.~ rb, Data.Mutable.Internal.Ref s c GHC.Types.~ rc, Data.Mutable.Internal.Ref s d GHC.Types.~ rd, Data.Mutable.Internal.Ref s e GHC.Types.~ re) => Data.Mutable.Internal.ListRefTuple s (ra, rb, rc, rd, re) '[a, b, c, d, e] instance (Data.Mutable.Internal.Ref s a GHC.Types.~ ra, Data.Mutable.Internal.Ref s b GHC.Types.~ rb, Data.Mutable.Internal.Ref s c GHC.Types.~ rc, Data.Mutable.Internal.Ref s d GHC.Types.~ rd, Data.Mutable.Internal.Ref s e GHC.Types.~ re, Data.Mutable.Internal.Ref s f GHC.Types.~ rf) => Data.Mutable.Internal.ListRefTuple s (ra, rb, rc, rd, re, rf) '[a, b, c, d, e, f] instance (Data.Mutable.Internal.Ref s a GHC.Types.~ ra, Data.Mutable.Internal.Ref s b GHC.Types.~ rb, Data.Mutable.Internal.Ref s c GHC.Types.~ rc, Data.Mutable.Internal.Ref s d GHC.Types.~ rd, Data.Mutable.Internal.Ref s e GHC.Types.~ re, Data.Mutable.Internal.Ref s f GHC.Types.~ rf, Data.Mutable.Internal.Ref s g GHC.Types.~ rg) => Data.Mutable.Internal.ListRefTuple s (ra, rb, rc, rd, re, rf, rg) '[a, b, c, d, e, f, g] instance (Data.Mutable.Internal.Ref s a GHC.Types.~ ra, Data.Mutable.Internal.Ref s b GHC.Types.~ rb, Data.Mutable.Internal.Ref s c GHC.Types.~ rc, Data.Mutable.Internal.Ref s d GHC.Types.~ rd, Data.Mutable.Internal.Ref s e GHC.Types.~ re, Data.Mutable.Internal.Ref s f GHC.Types.~ rf, Data.Mutable.Internal.Ref s g GHC.Types.~ rg, Data.Mutable.Internal.Ref s h GHC.Types.~ rh) => Data.Mutable.Internal.ListRefTuple s (ra, rb, rc, rd, re, rf, rg, rh) '[a, b, c, d, e, f, g, h] instance (Data.Mutable.Internal.Ref s a GHC.Types.~ ra, Data.Mutable.Internal.Ref s b GHC.Types.~ rb, Data.Mutable.Internal.Ref s c GHC.Types.~ rc, Data.Mutable.Internal.Ref s d GHC.Types.~ rd, Data.Mutable.Internal.Ref s e GHC.Types.~ re, Data.Mutable.Internal.Ref s f GHC.Types.~ rf, Data.Mutable.Internal.Ref s g GHC.Types.~ rg, Data.Mutable.Internal.Ref s h GHC.Types.~ rh, Data.Mutable.Internal.Ref s i GHC.Types.~ ri) => Data.Mutable.Internal.ListRefTuple s (ra, rb, rc, rd, re, rf, rg, rh, ri) '[a, b, c, d, e, f, g, h, i] instance (Data.Mutable.Internal.Ref s a GHC.Types.~ ra, Data.Mutable.Internal.Ref s b GHC.Types.~ rb, Data.Mutable.Internal.Ref s c GHC.Types.~ rc, Data.Mutable.Internal.Ref s d GHC.Types.~ rd, Data.Mutable.Internal.Ref s e GHC.Types.~ re, Data.Mutable.Internal.Ref s f GHC.Types.~ rf, Data.Mutable.Internal.Ref s g GHC.Types.~ rg, Data.Mutable.Internal.Ref s h GHC.Types.~ rh, Data.Mutable.Internal.Ref s i GHC.Types.~ ri, Data.Mutable.Internal.Ref s j GHC.Types.~ rj) => Data.Mutable.Internal.ListRefTuple s (ra, rb, rc, rd, re, rf, rg, rh, ri, rj) '[a, b, c, d, e, f, g, h, i, j] instance (Data.Mutable.Internal.Ref s a GHC.Types.~ ra, Data.Mutable.Internal.Ref s b GHC.Types.~ rb, Data.Mutable.Internal.Ref s c GHC.Types.~ rc, Data.Mutable.Internal.Ref s d GHC.Types.~ rd, Data.Mutable.Internal.Ref s e GHC.Types.~ re, Data.Mutable.Internal.Ref s f GHC.Types.~ rf, Data.Mutable.Internal.Ref s g GHC.Types.~ rg, Data.Mutable.Internal.Ref s h GHC.Types.~ rh, Data.Mutable.Internal.Ref s i GHC.Types.~ ri, Data.Mutable.Internal.Ref s j GHC.Types.~ rj, Data.Mutable.Internal.Ref s k GHC.Types.~ rk) => Data.Mutable.Internal.ListRefTuple s (ra, rb, rc, rd, re, rf, rg, rh, ri, rj, rk) '[a, b, c, d, e, f, g, h, i, j, k] instance (Data.Mutable.Internal.Ref s a GHC.Types.~ ra, Data.Mutable.Internal.Ref s b GHC.Types.~ rb, Data.Mutable.Internal.Ref s c GHC.Types.~ rc, Data.Mutable.Internal.Ref s d GHC.Types.~ rd, Data.Mutable.Internal.Ref s e GHC.Types.~ re, Data.Mutable.Internal.Ref s f GHC.Types.~ rf, Data.Mutable.Internal.Ref s g GHC.Types.~ rg, Data.Mutable.Internal.Ref s h GHC.Types.~ rh, Data.Mutable.Internal.Ref s i GHC.Types.~ ri, Data.Mutable.Internal.Ref s j GHC.Types.~ rj, Data.Mutable.Internal.Ref s k GHC.Types.~ rk, Data.Mutable.Internal.Ref s l GHC.Types.~ rl) => Data.Mutable.Internal.ListRefTuple s (ra, rb, rc, rd, re, rf, rg, rh, ri, rj, rk, rl) '[a, b, c, d, e, f, g, h, i, j, k, l] instance forall k s (f :: k -> *) (a :: k). GHC.Classes.Eq (Data.Mutable.Internal.Ref s (f a)) => GHC.Classes.Eq (Data.Mutable.Instances.RecRef s f a) instance forall k s (f :: k -> *) (a :: k). GHC.Classes.Ord (Data.Mutable.Internal.Ref s (f a)) => GHC.Classes.Ord (Data.Mutable.Instances.RecRef s f a) instance Data.Mutable.Internal.Mutable s (Data.Generics.Product.Internal.HList.HList '[]) instance (Data.Mutable.Internal.Mutable s a, Data.Mutable.Internal.Mutable s (Data.Generics.Product.Internal.HList.HList as), Data.Mutable.Internal.Ref s (Data.Generics.Product.Internal.HList.HList as) GHC.Types.~ Data.Mutable.Instances.HListRef s as) => Data.Mutable.Internal.Mutable s (Data.Generics.Product.Internal.HList.HList (a : as)) instance forall u s (f :: u -> *). Data.Mutable.Internal.Mutable s (Data.Vinyl.Core.Rec f '[]) instance forall a1 s (f :: a1 -> *) (a2 :: a1) (as :: [a1]). (Data.Mutable.Internal.Mutable s (f a2), Data.Mutable.Internal.Mutable s (Data.Vinyl.Core.Rec f as), Data.Mutable.Internal.Ref s (Data.Vinyl.Core.Rec f as) GHC.Types.~ Data.Vinyl.Core.Rec (Data.Mutable.Instances.RecRef s f) as) => Data.Mutable.Internal.Mutable s (Data.Vinyl.Core.Rec f (a2 : as)) instance forall k (as :: [k]) s (f :: k -> *). (Data.Vinyl.Core.RecApplicative as, Data.Vinyl.TypeLevel.NatToInt (Data.Vinyl.TypeLevel.RLength as), Data.Vinyl.Core.RPureConstrained (Data.Vinyl.ARec.IndexableField as) as, Data.Mutable.Internal.Mutable s (Data.Vinyl.Core.Rec f as), Data.Mutable.Internal.Ref s (Data.Vinyl.Core.Rec f as) GHC.Types.~ Data.Vinyl.Core.Rec (Data.Mutable.Instances.RecRef s f) as) => Data.Mutable.Internal.Mutable s (Data.Vinyl.ARec.ARec f as) instance (Data.Mutable.Internal.Mutable s a, Data.Mutable.Internal.Mutable s b, Data.Mutable.Internal.Mutable s c) => Data.Mutable.Internal.Mutable s (a, b, c) instance (Data.Mutable.Internal.Mutable s a, Data.Mutable.Internal.Mutable s b, Data.Mutable.Internal.Mutable s c, Data.Mutable.Internal.Mutable s d) => Data.Mutable.Internal.Mutable s (a, b, c, d) instance (Data.Mutable.Internal.Mutable s a, Data.Mutable.Internal.Mutable s b, Data.Mutable.Internal.Mutable s c, Data.Mutable.Internal.Mutable s d, Data.Mutable.Internal.Mutable s e) => Data.Mutable.Internal.Mutable s (a, b, c, d, e) instance (Data.Mutable.Internal.Mutable s a, Data.Mutable.Internal.Mutable s b, Data.Mutable.Internal.Mutable s c, Data.Mutable.Internal.Mutable s d, Data.Mutable.Internal.Mutable s e, Data.Mutable.Internal.Mutable s f) => Data.Mutable.Internal.Mutable s (a, b, c, d, e, f) instance (Data.Mutable.Internal.Mutable s a, Data.Mutable.Internal.Mutable s b, Data.Mutable.Internal.Mutable s c, Data.Mutable.Internal.Mutable s d, Data.Mutable.Internal.Mutable s e, Data.Mutable.Internal.Mutable s f, Data.Mutable.Internal.Mutable s g) => Data.Mutable.Internal.Mutable s (a, b, c, d, e, f, g) instance (Data.Mutable.Internal.Mutable s a, Data.Mutable.Internal.Mutable s b, Data.Mutable.Internal.Mutable s c, Data.Mutable.Internal.Mutable s d, Data.Mutable.Internal.Mutable s e, Data.Mutable.Internal.Mutable s f, Data.Mutable.Internal.Mutable s g, Data.Mutable.Internal.Mutable s h) => Data.Mutable.Internal.Mutable s (a, b, c, d, e, f, g, h) instance (Data.Mutable.Internal.Mutable s a, Data.Mutable.Internal.Mutable s b, Data.Mutable.Internal.Mutable s c, Data.Mutable.Internal.Mutable s d, Data.Mutable.Internal.Mutable s e, Data.Mutable.Internal.Mutable s f, Data.Mutable.Internal.Mutable s g, Data.Mutable.Internal.Mutable s h, Data.Mutable.Internal.Mutable s i) => Data.Mutable.Internal.Mutable s (a, b, c, d, e, f, g, h, i) instance (Data.Mutable.Internal.Mutable s a, Data.Mutable.Internal.Mutable s b, Data.Mutable.Internal.Mutable s c, Data.Mutable.Internal.Mutable s d, Data.Mutable.Internal.Mutable s e, Data.Mutable.Internal.Mutable s f, Data.Mutable.Internal.Mutable s g, Data.Mutable.Internal.Mutable s h, Data.Mutable.Internal.Mutable s i, Data.Mutable.Internal.Mutable s j) => Data.Mutable.Internal.Mutable s (a, b, c, d, e, f, g, h, i, j) instance (Data.Mutable.Internal.Mutable s a, Data.Mutable.Internal.Mutable s b, Data.Mutable.Internal.Mutable s c, Data.Mutable.Internal.Mutable s d, Data.Mutable.Internal.Mutable s e, Data.Mutable.Internal.Mutable s f, Data.Mutable.Internal.Mutable s g, Data.Mutable.Internal.Mutable s h, Data.Mutable.Internal.Mutable s i, Data.Mutable.Internal.Mutable s j, Data.Mutable.Internal.Mutable s k) => Data.Mutable.Internal.Mutable s (a, b, c, d, e, f, g, h, i, j, k) instance (Data.Mutable.Internal.Mutable s a, Data.Mutable.Internal.Mutable s b, Data.Mutable.Internal.Mutable s c, Data.Mutable.Internal.Mutable s d, Data.Mutable.Internal.Mutable s e, Data.Mutable.Internal.Mutable s f, Data.Mutable.Internal.Mutable s g, Data.Mutable.Internal.Mutable s h, Data.Mutable.Internal.Mutable s i, Data.Mutable.Internal.Mutable s j, Data.Mutable.Internal.Mutable s k, Data.Mutable.Internal.Mutable s l) => Data.Mutable.Internal.Mutable s (a, b, c, d, e, f, g, h, i, j, k, l) instance Data.Mutable.Internal.ListRefTuple s (Data.Mutable.Instances.UnitRef s) '[] instance (Data.Mutable.Internal.Ref s a GHC.Types.~ ra) => Data.Mutable.Internal.ListRefTuple s ra '[a] instance (Data.Mutable.Internal.Ref s a GHC.Types.~ ra, Data.Mutable.Internal.Ref s b GHC.Types.~ rb) => Data.Mutable.Internal.ListRefTuple s (ra, rb) '[a, b] instance Data.Foldable.Foldable Data.Mutable.Instances.UnitRef instance Data.Traversable.Traversable Data.Mutable.Instances.UnitRef instance GHC.Base.Functor Data.Mutable.Instances.UnitRef instance forall k (s :: k). GHC.Classes.Ord (Data.Mutable.Instances.UnitRef s) instance forall k (s :: k). GHC.Classes.Eq (Data.Mutable.Instances.UnitRef s) instance forall k (s :: k). GHC.Read.Read (Data.Mutable.Instances.UnitRef s) instance forall k (s :: k). GHC.Show.Show (Data.Mutable.Instances.UnitRef s) instance Data.Foldable.Foldable Data.Mutable.Instances.VoidRef instance Data.Traversable.Traversable Data.Mutable.Instances.VoidRef instance GHC.Base.Functor Data.Mutable.Instances.VoidRef instance forall k (s :: k). GHC.Classes.Ord (Data.Mutable.Instances.VoidRef s) instance forall k (s :: k). GHC.Classes.Eq (Data.Mutable.Instances.VoidRef s) instance forall k (s :: k). GHC.Read.Read (Data.Mutable.Instances.VoidRef s) instance forall k (s :: k). GHC.Show.Show (Data.Mutable.Instances.VoidRef s) instance GHC.Base.Applicative Data.Mutable.Instances.UnitRef instance GHC.Base.Monad Data.Mutable.Instances.UnitRef instance Data.Mutable.Internal.Mutable s () instance Data.Mutable.Internal.Mutable s Data.Void.Void instance Data.Mutable.Internal.Mutable s GHC.Types.Int instance Data.Mutable.Internal.Mutable s GHC.Integer.Type.Integer instance Data.Mutable.Internal.Mutable s GHC.Natural.Natural instance Data.Mutable.Internal.Mutable s (GHC.Real.Ratio a) instance Data.Mutable.Internal.Mutable s GHC.Types.Float instance Data.Mutable.Internal.Mutable s GHC.Types.Double instance Data.Mutable.Internal.Mutable s (Data.Complex.Complex a) instance Data.Mutable.Internal.Mutable s GHC.Types.Bool instance Data.Mutable.Internal.Mutable s GHC.Types.Char instance Data.Mutable.Internal.Mutable s GHC.Types.Word instance Data.Mutable.Internal.Mutable s GHC.Word.Word8 instance Data.Mutable.Internal.Mutable s GHC.Word.Word16 instance Data.Mutable.Internal.Mutable s GHC.Word.Word64 instance Data.Mutable.Internal.Mutable s Foreign.C.Types.CChar instance Data.Mutable.Internal.Mutable s Foreign.C.Types.CSChar instance Data.Mutable.Internal.Mutable s Foreign.C.Types.CUChar instance Data.Mutable.Internal.Mutable s Foreign.C.Types.CShort instance Data.Mutable.Internal.Mutable s Foreign.C.Types.CUShort instance Data.Mutable.Internal.Mutable s Foreign.C.Types.CInt instance Data.Mutable.Internal.Mutable s Foreign.C.Types.CUInt instance Data.Mutable.Internal.Mutable s Foreign.C.Types.CLong instance Data.Mutable.Internal.Mutable s Foreign.C.Types.CULong instance Data.Mutable.Internal.Mutable s Foreign.C.Types.CPtrdiff instance Data.Mutable.Internal.Mutable s Foreign.C.Types.CSize instance Data.Mutable.Internal.Mutable s Foreign.C.Types.CWchar instance Data.Mutable.Internal.Mutable s Foreign.C.Types.CSigAtomic instance Data.Mutable.Internal.Mutable s Foreign.C.Types.CLLong instance Data.Mutable.Internal.Mutable s Foreign.C.Types.CULLong instance Data.Mutable.Internal.Mutable s Foreign.C.Types.CBool instance Data.Mutable.Internal.Mutable s Foreign.C.Types.CIntPtr instance Data.Mutable.Internal.Mutable s Foreign.C.Types.CUIntPtr instance Data.Mutable.Internal.Mutable s Foreign.C.Types.CIntMax instance Data.Mutable.Internal.Mutable s Foreign.C.Types.CUIntMax instance Data.Mutable.Internal.Mutable s Foreign.C.Types.CClock instance Data.Mutable.Internal.Mutable s Foreign.C.Types.CTime instance Data.Mutable.Internal.Mutable s Foreign.C.Types.CUSeconds instance Data.Mutable.Internal.Mutable s Foreign.C.Types.CSUSeconds instance Data.Mutable.Internal.Mutable s Foreign.C.Types.CFloat instance Data.Mutable.Internal.Mutable s Foreign.C.Types.CDouble instance Data.Mutable.Internal.Mutable s a => Data.Mutable.Internal.Mutable s (Data.Functor.Identity.Identity a) instance forall k s a (b :: k). Data.Mutable.Internal.Mutable s a => Data.Mutable.Internal.Mutable s (Data.Functor.Const.Const a b) instance forall k s a (b :: k). Data.Mutable.Internal.Mutable s a => Data.Mutable.Internal.Mutable s (Data.Vinyl.Functor.Const a b) instance Data.Mutable.Internal.Mutable s a => Data.Mutable.Internal.Mutable s (Data.Semigroup.Internal.Product a) instance Data.Mutable.Internal.Mutable s a => Data.Mutable.Internal.Mutable s (Data.Semigroup.Internal.Sum a) instance Data.Mutable.Internal.Mutable s a => Data.Mutable.Internal.Mutable s (Data.Ord.Down a) instance Data.Mutable.Internal.Mutable s a => Data.Mutable.Internal.Mutable s (Data.Semigroup.Internal.Dual a) instance Data.Mutable.Internal.Mutable s a => Data.Mutable.Internal.Mutable s (GHC.Maybe.Maybe a) instance (Data.Mutable.Internal.Mutable s a, Data.Mutable.Internal.Mutable s b) => Data.Mutable.Internal.Mutable s (Data.Either.Either a b) instance forall k s (f :: k -> *) (a :: k) (g :: k -> *). (Data.Mutable.Internal.Mutable s (f a), Data.Mutable.Internal.Mutable s (g a)) => Data.Mutable.Internal.Mutable s (Data.Functor.Product.Product f g a) instance forall k s (f :: k -> *) (a :: k) (g :: k -> *). (Data.Mutable.Internal.Mutable s (f a), Data.Mutable.Internal.Mutable s (g a)) => Data.Mutable.Internal.Mutable s (Data.Functor.Sum.Sum f g a) instance forall k k1 s (f :: k -> *) (g :: k1 -> k) (a :: k1). Data.Mutable.Internal.Mutable s (f (g a)) => Data.Mutable.Internal.Mutable s (Data.Functor.Compose.Compose f g a) instance Data.Mutable.Internal.Mutable s a => Data.Mutable.Internal.Mutable s [a] instance Data.Mutable.Internal.Mutable s a => Data.Mutable.Internal.Mutable s (Data.Vinyl.Functor.Identity a) instance Data.Mutable.Internal.Mutable s (Data.Vector.Vector a) instance Foreign.Storable.Storable a => Data.Mutable.Internal.Mutable s (Data.Vector.Storable.Vector a) instance Data.Vector.Unboxed.Base.Unbox a => Data.Mutable.Internal.Mutable s (Data.Vector.Unboxed.Base.Vector a) instance Data.Primitive.Types.Prim a => Data.Mutable.Internal.Mutable s (Data.Vector.Primitive.Vector a) instance Data.Mutable.Internal.Mutable s (Data.Primitive.Array.Array a) instance Data.Mutable.Internal.Mutable s (Data.Primitive.SmallArray.SmallArray a) instance Data.Mutable.Internal.Mutable s Data.Primitive.ByteArray.ByteArray instance Data.Primitive.Types.Prim a => Data.Mutable.Internal.Mutable s (Data.Primitive.PrimArray.PrimArray a) instance (Data.Mutable.Internal.Mutable s a, Data.Mutable.Internal.Mutable s b) => Data.Mutable.Internal.Mutable s (a, b) -- | Provides the Mutable typeclass and various helpers. See -- Data.Mutable for the main "entrypoint". Many of the datatypes -- used for Ref instances are defined in -- Data.Mutable.Instances module Data.Mutable.Class -- | An instance of Mutable s a means that a can -- be stored a mutable reference in a PrimMonad m (where -- s is the mutable state token PrimState of that monad). -- -- The associated type Ref s a links any a to -- the type of its canonical mutable version. -- -- The benefit of this typeclass, instead of just using -- IORef or MutVar or specific mutable versions like -- Vector and MVector, is two-fold: -- --
instance (Mutable s a, Mutable s b) => -- Mutable s (a, b)If a and b are -- piecwise-mutable, then the instance here will appropriately utilize -- that fact.
-- data TwoVectors = TV
-- { tvInt :: Vector Int
-- , tvDouble :: Vector Double
-- }
-- deriving Generic
--
-- instance Mutable s TwoVectors where
-- type Ref s TwoVectors = GRef s TwoVectors
--
--
-- Then now we get:
--
-- -- thawRef :: TwoVectors -> m (GRef s TwoVectors) -- freezeRef :: GRef s TwoVectors -> m TwoVectors ---- -- And GRef s 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 MVectors. 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 -- TwoVectors. 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 -- https://reasonablypolymorphic.com/blog/higher-kinded-data/, -- then we can also do: -- --
-- data TwoVectors f = TV
-- { tvInt :: HKD f (Vector Int)
-- , tvDouble :: HKD f (Vector Double)
-- }
-- deriving Generic
--
-- instance Mutable (TwoVectors Identity) where
-- type Ref (TwoVectors Identity) = TwoVectors (RefFor s)
--
--
-- 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 RealWorld) -- ghci> :t is -- 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 s MyType = CoerceRef s 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 s (MyContainer a) = TraverseRef s MyContainer a ---- -- See https://mutable.jle.im/02-mutable-and-ref.html for more -- information on this typeclass and how to define instances -- automatically, and also -- --
-- type Ref s (Vector a) = MVector s a
--
--
-- This means that using thawRef on a Vector will give you
-- an MVector, using freezeRef on a Vector will give
-- you a Vector, etc.
--
--
-- thawRef
-- :: (PrimMonad m, PrimState m ~ s)
-- => Vector a
-- -> m (Vector s a)
--
-- freezeRef
-- :: (PrimMonad m, PrimState m ~ s)
-- => Vector s a
-- -> m (Vector a)
--
-- copyRef
-- :: (PrimMonad m, PrimState m ~ s)
-- => Vector s a
-- -> Vector a
-- -> m ()
--
--
-- This associated type must be unique for a, so no two types
-- a can have the same Ref s a. This makes type
-- inference a lot more useful: if you use freezeRef on an
-- MVector, for instance, the return type will be inferred to be
-- 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 s a = GRef s 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 s MyType
--
-- -- This is equivalent to the above
-- instance Mutable s MyType
-- type Ref s MyType = MutVar s MyType
--
-- -- any Generic instance
-- data MyType = MyType { mtInt :: Int, mtDouble :: Double }
-- deriving Generic
--
-- instance Mutable s MyType where
-- type Ref s MyType = GRef s MyType
--
--
-- See https://mutable.jle.im/02-mutable-and-ref.html for more
-- information on this type family and how to define instances
-- automatically.
--
-- Note that this type synonym ins injective --- this means that if you
-- write a function polymorphic over Ref s a, you can
-- always infer s and a (the value stored in the
-- Ref).
--
-- In practice, if you want to write your own instance from scratch, the
-- consequence is that you must have the s type variable
-- somewhere in your type (see UnitRef and VoidRef for
-- examples).
type family Ref s a = (v :: Type) | v -> a s;
type Ref s a = MutVar s a;
}
-- | Thaw a pure/persistent value into its mutable version, which
-- can be manipulated using modifyRef or other methods specific
-- for that type (like read).
--
-- Returns the Ref instance, so, for example, for Vector:
--
-- -- thawRef -- :: (PrimMonad m, PrimState m ~ s) -- => Vector a -- -> m (Vector s a) ---- -- For non-composite (like Int), this is often called the "new -- var" function, like newIORef / newSTRef / -- newMutVar etc. thawRef :: (Mutable s a, PrimMonad m, PrimState m ~ s) => a -> m (Ref s 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 Vector: -- --
-- freezeRef -- :: (PrimMonad m, PrimState m ~ s) -- => Vector s a -- -> m (Vector a) ---- -- For non-composite (like Int), this is often called the "read -- var" function, like readIORef / readSTRef / -- readMutVar etc. freezeRef :: (Mutable s a, PrimMonad m, PrimState m ~ s) => Ref s a -> m a -- | Overwrite a mutable value by provivding a pure/persistent value. -- copyRef -- -- Returns the Ref and the value, so, for example, for -- Vector: -- --
-- copyRef -- :: (PrimMonad m, PrimState m ~ s) -- => Vector s a -- -> 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 writeIORef / writeSTRef / -- writeMutVar etc. copyRef :: (Mutable s a, PrimMonad m, PrimState m ~ s) => Ref s a -> a -> 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 :: (Mutable s a, PrimMonad m, PrimState m ~ s) => Ref s a -> Ref s a -> 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 :: (Mutable s a, PrimMonad m, PrimState m ~ s) => Ref s a -> m (Ref s 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 Vector). -- -- This is safe as long as you never again use the original pure value, -- since it can potentially directly mutate it. unsafeThawRef :: (Mutable s a, PrimMonad m, PrimState m ~ s) => a -> m (Ref s 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 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 :: (Mutable s a, PrimMonad m, PrimState m ~ s) => Ref s a -> m a -- | Thaw a pure/persistent value into its mutable version, which -- can be manipulated using modifyRef or other methods specific -- for that type (like read). -- -- Returns the Ref instance, so, for example, for Vector: -- --
-- thawRef -- :: (PrimMonad m, PrimState m ~ s) -- => Vector a -- -> m (Vector s a) ---- -- For non-composite (like Int), this is often called the "new -- var" function, like newIORef / newSTRef / -- newMutVar etc. thawRef :: (Mutable s a, DefaultMutable s a (Ref s a), PrimMonad m, PrimState m ~ s) => a -> m (Ref s 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 Vector: -- --
-- freezeRef -- :: (PrimMonad m, PrimState m ~ s) -- => Vector s a -- -> m (Vector a) ---- -- For non-composite (like Int), this is often called the "read -- var" function, like readIORef / readSTRef / -- readMutVar etc. freezeRef :: (Mutable s a, DefaultMutable s a (Ref s a), PrimMonad m, PrimState m ~ s) => Ref s a -> m a -- | Overwrite a mutable value by provivding a pure/persistent value. -- copyRef -- -- Returns the Ref and the value, so, for example, for -- Vector: -- --
-- copyRef -- :: (PrimMonad m, PrimState m ~ s) -- => Vector s a -- -> 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 writeIORef / writeSTRef / -- writeMutVar etc. copyRef :: (Mutable s a, DefaultMutable s a (Ref s a), PrimMonad m, PrimState m ~ s) => Ref s a -> a -> 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 :: (Mutable s a, DefaultMutable s a (Ref s a), PrimMonad m, PrimState m ~ s) => Ref s a -> Ref s a -> 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 :: (Mutable s a, DefaultMutable s a (Ref s a), PrimMonad m, PrimState m ~ s) => Ref s a -> m (Ref s 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 Vector). -- -- This is safe as long as you never again use the original pure value, -- since it can potentially directly mutate it. unsafeThawRef :: (Mutable s a, DefaultMutable s a (Ref s a), PrimMonad m, PrimState m ~ s) => a -> m (Ref s 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 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 :: (Mutable s a, DefaultMutable s a (Ref s a), PrimMonad m, PrimState m ~ s) => Ref s a -> m a -- | A default implementation of copyRef using thawRef and -- moveRef. copyRefWhole :: (Mutable s a, PrimMonad m, PrimState m ~ s) => Ref s a -> a -> m () -- | A default implementation of moveRef that round-trips through -- the pure type, using freezeRef and copyRef. It freezes -- the entire source and then re-copies it into the destination. moveRefWhole :: (Mutable s a, PrimMonad m, PrimState m ~ s) => Ref s a -> Ref s a -> m () -- | A default implementation of moveRef that round-trips through -- the pure type, using freezeRef and thawRef. It freezes -- the entire source and then re-copies it into the destination. cloneRefWhole :: (Mutable s a, PrimMonad m, PrimState m ~ s) => Ref s a -> m (Ref s a) -- | Apply a pure function on an immutable value onto a value stored in a -- mutable reference. modifyRef :: (Mutable s a, PrimMonad m, PrimState m ~ s) => Ref s a -> (a -> a) -> m () -- | modifyRef, but forces the result before storing it back in the -- reference. modifyRef' :: (Mutable s a, PrimMonad m, PrimState m ~ s) => Ref s a -> (a -> a) -> m () -- | Apply a pure function on an immutable value onto a value stored in a -- mutable reference, returning a result value from that function. updateRef :: (Mutable s a, PrimMonad m, PrimState m ~ s) => Ref s a -> (a -> (a, b)) -> m b -- | updateRef, but forces the updated value before storing it back -- in the reference. updateRef' :: (Mutable s a, PrimMonad m, PrimState m ~ s) => Ref s a -> (a -> (a, b)) -> m b -- | Apply a monadic function on an immutable value onto a value stored in -- a mutable reference. Uses copyRef into the reference after the -- action is completed. modifyRefM :: (Mutable s a, PrimMonad m, PrimState m ~ s) => Ref s a -> (a -> m a) -> m () -- | modifyRefM, but forces the result before storing it back in the -- reference. modifyRefM' :: (Mutable s a, PrimMonad m, PrimState m ~ s) => Ref s a -> (a -> m a) -> m () -- | Apply a monadic function on an immutable value onto a value stored in -- a mutable reference, returning a result value from that function. Uses -- copyRef into the reference after the action is completed. updateRefM :: (Mutable s a, PrimMonad m, PrimState m ~ s) => Ref s a -> (a -> m (a, b)) -> m b -- | updateRefM, but forces the updated value before storing it back -- in the reference. updateRefM' :: (Mutable s a, PrimMonad m, PrimState m ~ s) => Ref s a -> (a -> m (a, b)) -> m b -- | A handy newtype wrapper that allows you to partially apply Ref. -- RefFor m a is the same as Ref s a, but -- can be partially applied. -- -- If used with HKD, you can treat this syntactically identically -- as a Ref s a. newtype RefFor s a RefFor :: Ref s a -> RefFor s a [getRefFor] :: RefFor s a -> Ref s a -- | 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 s MyType -- -- -- the above is the same as: -- instance Mutable s MyType -- type Ref s MyType = MutVar s) MyType ---- -- The case for any instance of Generic: -- --
-- instance Mutable s MyType -- type Ref s MyType = GRef s MyType ---- -- The case for the "higher-kinded data" pattern a la -- https://reasonablypolymorphic.com/blog/higher-kinded-data/: -- --
-- instance Mutable s (MyTypeF Identity) -- type Ref s (MyTypeF Identity) = MyTypeF (RefFor s) ---- -- The case for any newtype wrapper: -- --
-- newtype MyType = MT (Vector Double) -- -- instance Mutable s MyType where -- type Ref s MyType = CoerceRef s 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 s a => Mutable s (MyContainer a) where -- type Ref s (MyContainer a) = TraverseRef s MyContainer a --class DefaultMutable s a r | r -> a s defaultThawRef :: (DefaultMutable s a r, PrimMonad m, PrimState m ~ s) => a -> m r defaultFreezeRef :: (DefaultMutable s a r, PrimMonad m, PrimState m ~ s) => r -> m a defaultCopyRef :: (DefaultMutable s a r, PrimMonad m, PrimState m ~ s) => r -> a -> m () defaultMoveRef :: (DefaultMutable s a r, PrimMonad m, PrimState m ~ s) => r -> r -> m () defaultCloneRef :: (DefaultMutable s a r, PrimMonad m, PrimState m ~ s) => r -> m r defaultUnsafeThawRef :: (DefaultMutable s a r, PrimMonad m, PrimState m ~ s) => a -> m r defaultUnsafeFreezeRef :: (DefaultMutable s a r, PrimMonad m, PrimState m ~ s) => r -> m a -- | Newtype wrapper that can provide any type with a Mutable -- instance, giving it a "non-piecewise" instance. Can be useful for -- avoiding orphan instances yet still utilizing auto-deriving features, -- or for overwriting the Mutable instance of other instances. -- -- For example, let's say you want to auto-derive an instance for your -- data type: -- --
-- data MyType = MT Int Double OtherType -- deriving Generic ---- -- This is possible if all of MyTypes fields have Mutable -- instances. However, let's say OtherType comes from an -- external library that you don't have control over, and so you cannot -- give it a Mutable instance without incurring an orphan -- instance. -- -- One solution is to wrap it in VarMut: -- --
-- data MyType = MT Int Double (VarMut OtherType) -- deriving Generic ---- -- This can then be auto-derived: -- --
-- instance Mutable s MyType where -- type Ref s MyType = GRef s MyType ---- -- It can also be used to override a Mutable instance. For -- example, even if the Mutable instance of SomeType is -- piecewise-mutable, the Mutable instance of VarMut -- SomeType will be not be piecewise. -- -- For example, the Mutable instance for String is a -- mutable linked list, but it might be more efficient to treat it as an -- atomic value to update all at once. You can use VarMut -- String to get that Mutable instance. newtype VarMut a VarMut :: a -> VarMut a [getVarMut] :: VarMut a -> a -- | Similar to VarMut, this allows you to overwrite the normal -- Mutable instance of a type to utilize a coercible type's -- Mutable instance instead of its normal instance. It's also -- useful to provide an instance for an externally defined type without -- incurring orphan instances. -- -- For example, if an external library provides -- --
-- newtype DoubleVec = DV (Vector Double) ---- -- and you want to use it following Vectors Mutable -- instance (via MVector), but you don't want to write an orphan -- instance like -- --
-- instance Mutable s DoubleVec where -- type Ref s DoubleVec = CoerceRef s DoubleVec (Vector Double) ---- -- then you can instead use CoerceMut DoubleVec (Vector -- Double) as the data type. This wrapped type does use the -- inderlying Mutable insatnce for Vector. newtype CoerceMut s a CoerceMut :: s -> CoerceMut s a [getCoerceMut] :: CoerceMut s a -> s -- | Similar to VarMut, this allows you to overwrite the normal -- Mutable instance for a type to utilize its Traversable -- instance instead of its normal instance. It's also useful to provide -- an instance for an externally defined type without incurring orphan -- instances. -- -- For example, the instance of Mutable (TraverseMut [] -- a) is a normal list of mutable references, instead of a full-on -- mutable linked list. newtype TraverseMut f a TraverseMut :: f a -> TraverseMut f a [getTraverseMut] :: TraverseMut f a -> f a -- | Similar to VarMut, this allows you to overwrite the normal -- Mutable instance of a type to make it immutable. -- -- For example, let's say you have a type, with the automatically derived -- generic instance of Mutable: -- --
-- data MyType = MT
-- { mtX :: Int
-- , mtY :: Vector Double
-- , mtZ :: String
-- }
-- deriving Generic
--
-- instance Mutable s MyType where
-- type Ref s MyType = GRef s MyType
--
--
-- This basically uses three mutable references: the Int, the
-- Vector Double, and the String. However, you
-- might want the Mutable instance of MyType to be
-- immutable String field, and so it cannot be updated at
-- all even when thawed. To do that, you can instead have:
--
--
-- data MyType = MT
-- { mtX :: Int
-- , mtY :: Vector Double
-- , mtZ :: Immutable String
-- }
-- deriving Generic
--
-- instance Mutable s MyType where
-- type Ref s MyType = GRef s MyType
--
--
-- which has that behavior. The Int and the Vector will be
-- mutable within Ref s MyType, but not the
-- String.
newtype Immutable s a
Immutable :: a -> Immutable s a
[getImmutable] :: Immutable s a -> a
-- | Useful type family to Ref m over every item in a
-- type-level list
--
-- -- ghci> :kind! MapRef IO '[Int, V.Vector Double] -- '[ MutVar RealWorld Int, MVector RealWorld Double ] --type family MapRef s as instance Data.Traversable.Traversable f => Data.Traversable.Traversable (Data.Mutable.Class.TraverseMut f) instance Data.Foldable.Foldable f => Data.Foldable.Foldable (Data.Mutable.Class.TraverseMut f) instance GHC.Base.Functor f => GHC.Base.Functor (Data.Mutable.Class.TraverseMut f) instance forall k (f :: k -> *) (a :: k). GHC.Generics.Generic (Data.Mutable.Class.TraverseMut f a) instance forall k (f :: k -> *) (a :: k). GHC.Classes.Ord (f a) => GHC.Classes.Ord (Data.Mutable.Class.TraverseMut f a) instance forall k (f :: k -> *) (a :: k). GHC.Classes.Eq (f a) => GHC.Classes.Eq (Data.Mutable.Class.TraverseMut f a) instance forall k (f :: k -> *) (a :: k). GHC.Show.Show (f a) => GHC.Show.Show (Data.Mutable.Class.TraverseMut f a) instance forall k (s :: k) a. Data.Vinyl.XRec.IsoHKD (Data.Mutable.Class.Immutable s) a instance Data.Mutable.Internal.Mutable s (Data.Mutable.Class.Immutable s a) instance forall k s (a :: k). Data.Vinyl.XRec.IsoHKD (Data.Mutable.Class.CoerceMut s) a instance (Data.Mutable.Internal.Mutable s a, GHC.Types.Coercible s a) => Data.Mutable.Internal.Mutable s (Data.Mutable.Class.CoerceMut s a) instance forall k (f :: k -> *) (a :: k). Data.Vinyl.XRec.IsoHKD (Data.Mutable.Class.TraverseMut f) a instance (Data.Traversable.Traversable f, Data.Mutable.Internal.Mutable s a) => Data.Mutable.Internal.Mutable s (Data.Mutable.Class.TraverseMut f a) instance Data.Vinyl.XRec.IsoHKD Data.Mutable.Class.VarMut a instance Data.Mutable.Internal.Mutable s (Data.Mutable.Class.VarMut a) -- | Tools for working with potential branches of piecewise-mutable values. -- -- If Data.Mutable.Parts is for product types, then -- Data.Mutable.Branches is for sum types. -- -- See https://mutable.jle.im/06-mutable-branches.html for an -- introduction to this module. module Data.Mutable.Branches -- | A MutBranch s b a represents the information that -- b could potentially be an a. Similar in spirit to a -- Prism' b a. -- -- MutBranch s b a means that a is one potential -- option that b could be in, or that b is a sum type -- and a is one of the branches/constructors. -- -- See https://mutable.jle.im/06-mutable-branches.html for an -- introduction to this module. -- -- If MutPart is for product types, then MutBranch is for -- sum types. -- -- In this case, "branch" means "potential option". For example, the -- branches of Either are Left and Right. -- -- The simplest way to make these is by using constrMB. For -- instance, to get the two branches of an Either: -- --
-- constrMB #_Left :: MutBranch s (Either a b) a -- constrMB #_Right :: MutBranch s (Either a b) b ---- --
-- ghci> r <- thawRef (Left 10) -- ghci> freezeBranch (constrMB #_Left) r -- Just 10 -- ghci> freezeBranch (constrMB #_Right) r -- Nothing ---- -- It uses OverloadedLabels, but requires an underscore before the -- constructor name due to limitations in the extension. -- -- One nice way to use these is with withBranch_: -- --
-- ghci> r <- thawRef (Just 10) -- ghci> withBranch_ (constrMB #_Just) $ i -> -- i is an Int ref -- .. modifyRef i (+ 1) -- ghci> freezeRef r -- Just 11 ---- --
-- ghci> r <- thawRef Nothing -- ghci> withBranch_ (constrMB #_Just) $ i -> -- i is an Int ref -- .. modifyRef i (+ 1) -- ghci> freezeRef r -- Nothing ---- -- Perhaps the most useful usage of this abstraction is for recursive -- data types. -- --
-- data List a = Nil | Cons a (List a) -- deriving Generic -- -- instance Mutable s a => Mutable s (List a) where -- type Ref s (List a) = GRef s (List a) ---- -- GRef s (List a) is now a mutable linked list! Once we -- make the MutBranch for the nil and cons cases: -- --
-- nilBranch :: MutBranch s (List a) () -- nilBranch = constrMB #_Nil -- -- consBranch :: MutBranch s (List a) (a, List a) -- consBranch = constrMB #_Cons ---- -- Here is a function to check if a linked list is currently empty: -- --
-- isEmpty -- :: (PrimMonad m, Mutable s a) -- => Ref s (List a) -- -> m Bool -- isEmpty = hasBranch nilBranch ---- -- Here is one to "pop" a mutable linked list, giving us the first value -- and shifting the rest of the list up. -- --
-- popStack -- :: (PrimMonad m, Mutable s a) -- => Ref s (List a) -- -> m (Maybe a) -- popStack r = do -- c <- projectBranch consBranch r -- case c of -- Nothing -> pure Nothing -- Just (x, xs) -> do -- moveRef r xs -- Just $ freezeRef x ---- -- And here is a function to concatenate a second linked list to the end -- of a first one. -- --
-- concatLists -- :: (PrimMonad m, Mutable s a) -- => Ref s (List a) -- -> Ref s (List a) -- -> m () -- concatLists l1 l2 = do -- c <- projectBranch consBranch l1 -- case c of -- Nothing -> moveRef l1 l2 -- Just (_, xs) -> concatLists xs l2 --data MutBranch s b a MutBranch :: (forall m. (PrimMonad m, PrimState m ~ s) => Ref s b -> m (Maybe (Ref s a))) -> (forall m. (PrimMonad m, PrimState m ~ s) => Ref s a -> m (Ref s b)) -> MutBranch s b a -- | With a MutBranch, attempt to get the mutable contents of a -- branch of a mutable s, if possible. -- --
-- ghci> r <- thawRef (Left 10) -- ghci> s <- projectBranch (constrMB #_Left) r -- ghci> case s of Just s' -> freezeRef s' -- 10 ---- --
-- ghci> r <- thawRef (Right True) -- ghci> s <- projectBranch (constrMB #_Left) r -- ghci> case s of Nothing -> "it was Right" -- "it was Right" --[projectBranch] :: MutBranch s b a -> forall m. (PrimMonad m, PrimState m ~ s) => Ref s b -> m (Maybe (Ref s a)) -- | Embed an a ref as a part of a larger s ref. Note -- that this does not copy or clone: any mutations to the -- a ref will be reflected in the s ref, as long as the -- s ref maintains the reference. -- --
-- ghci> r <- thawRef 100 -- ghci> s <- embedBranch (constMB #_Left) r -- ghci> freezeRef s -- Left 100 -- ghci> modifyRef r (+ 1) -- ghci> freezeRef s -- Left 101 ---- -- Any mutations on s (as long as they keep the same branch) -- will also affect a: -- --
-- ghci> copyRef s (Left 0) -- ghci> freezeRef r -- 0 ---- -- However, "switching branches" on an Either ref will cause it to -- loose the original reference: -- --
-- ghci> copyRef s (Right True) -- ghci> copyRef s (Left 999) -- ghci> freezeRef r -- 0 --[embedBranch] :: MutBranch s b a -> forall m. (PrimMonad m, PrimState m ~ s) => Ref s a -> m (Ref s b) -- | With a MutBranch, thaw an a into a mutable s -- on that branch. -- --
-- ghci> r <- thawBranch (constrMB #_Left) 10 -- ghci> freezeRef r -- Left 10 --thawBranch :: (Mutable s a, PrimMonad m, PrimState m ~ s) => MutBranch s b a -> a -> m (Ref s b) -- | With a MutBranch, read out a specific a branch of an -- s, if it exists. -- --
-- ghci> r <- thawRef (Left 10) -- ghci> freezeBranch (constrMB #_Left) r -- Just 10 -- ghci> freezeBranch (constrMB #_Right) r -- Nothing --freezeBranch :: (Mutable s a, PrimMonad m, PrimState m ~ s) => MutBranch s b a -> Ref s b -> m (Maybe a) -- | Check if an s is currently a certain branch a. hasBranch :: (PrimMonad m, PrimState m ~ s) => MutBranch s b a -> Ref s b -> m Bool -- | Check if an s is not currently a certain branch -- a. hasn'tBranch :: (PrimMonad m, PrimState m ~ s) => MutBranch s b a -> Ref s b -> m Bool -- | With a MutBranch, overwrite an s as an a, on -- that branch. -- --
-- ghci> r <- thawRef (Left 10) -- ghci> s <- thawRef 100 -- ghci> moveBranch (constrMB #_Left) r s -- ghci> freezeRef r -- Left 100 -- ghci> t <- thawRef True -- ghci> moveBranch (constrMB #_Right) r t -- ghci> freezeRef r -- Right True --moveBranch :: (Mutable s b, PrimMonad m, PrimState m ~ s) => MutBranch s b a -> Ref s b -> Ref s a -> m () -- | With a MutBranch, set s to have the branch -- a. -- --
-- ghci> r <- thawRef (Left 10) -- ghci> copyBranch (constrMB #_Left) r 5678 -- ghci> freezeRef r -- Left 5678 -- ghci> copyBranch (constrMB #_Right) r True -- ghci> freezeRef r -- Right True --copyBranch :: (Mutable s b, Mutable s a, PrimMonad m, PrimState m ~ s) => MutBranch s b a -> Ref s b -> a -> m () -- | With a MutBranch, attempt to clone out a branch of a mutable -- s, if possible. -- --
-- ghci> r <- thawRef (Left 10) -- ghci> s <- cloneBranch (constrMB #_Left) -- ghci> case s of Just s' -> freezeRef s' -- 10 ---- --
-- ghci> r <- thawRef (Right True) -- ghci> s <- cloneBranch (constrMB #_Left) -- ghci> case s of Nothing -> "it was Right" -- "it was Right" --cloneBranch :: (Mutable s a, PrimMonad m, PrimState m ~ s) => MutBranch s b a -> Ref s b -> m (Maybe (Ref s a)) -- | A non-copying version of thawBranch that can be more efficient -- for types where the mutable representation is the same as the -- immutable one (like Vector). -- -- This is safe as long as you never again use the original pure value, -- since it can potentially directly mutate it. unsafeThawBranch :: (Mutable s a, PrimMonad m, PrimState m ~ s) => MutBranch s b a -> a -> m (Ref s b) -- | A non-copying version of freezeBranch that can be more -- efficient for types where the mutable representation is the same as -- the immutable one (like Vector). -- -- This is safe as long as you never again modify the mutable reference, -- since it can potentially directly mutate the frozen value magically. unsafeFreezeBranch :: (Mutable s a, PrimMonad m, PrimState m ~ s) => MutBranch s b a -> Ref s b -> m (Maybe a) -- | With a MutBranch, if an s is on the a branch, -- perform an action on the a reference and overwrite the -- s with the modified a. Returns the result of the -- action, if a was found. -- --
-- ghci> r <- thawRef (Just 10) -- ghci> withBranch_ (constrMB #_Just) $ i -> -- i is an Int ref -- .. modifyRef i (+ 1) -- ghci> freezeRef r -- Just 11 ---- --
-- ghci> r <- thawRef Nothing -- ghci> withBranch_ (constrMB #_Just) $ i -> -- i is an Int ref -- .. modifyRef i (+ 1) -- ghci> freezeRef r -- Nothing --withBranch :: (PrimMonad m, PrimState m ~ s) => MutBranch s b a -> Ref s b -> (Ref s a -> m r) -> m (Maybe r) -- | withBranch, but discarding the returned value. withBranch_ :: (PrimMonad m, PrimState m ~ s) => MutBranch s b a -> Ref s b -> (Ref s a -> m r) -> m () -- | With a MutBranch, run a pure function over a potential branch -- a of s. If s is not on that branch, leaves -- s unchanged. -- --
-- ghci> r <- thawRef (Just 10) -- ghci> modifyBranch (constrMB #_Just) r (+ 1) -- ghci> freezeRef r -- Just 11 ---- --
-- ghci> r <- thawRef Nothing -- ghci> modifyBranch (constrMB #_Just) r (+ 1) -- ghci> freezeRef r -- Nothing --modifyBranch :: (Mutable s a, PrimMonad m, PrimState m ~ s) => MutBranch s b a -> Ref s b -> (a -> a) -> m () -- | modifyBranch, but forces the result before storing it back in -- the reference. modifyBranch' :: (Mutable s a, PrimMonad m, PrimState m ~ s) => MutBranch s b a -> Ref s b -> (a -> a) -> m () -- | With a MutBranch, run a pure function over a potential branch -- a of s. The function returns the updated a -- and also an output value to observe. If s is not on that -- branch, leaves s unchanged. -- --
-- ghci> r <- thawRef (Just 10) -- ghci> updateBranch (constrMB #_Just) r $ i -> (i + 1, show i) -- Just "10" -- ghci> freezeRef r -- Just 11 ---- --
-- ghci> r <- thawRef Nothing -- ghci> updateBranch (constrMB #_Just) r $ i -> (i + 1, show i) -- Nothing -- ghci> freezeRef r -- Nothing --updateBranch :: (Mutable s a, PrimMonad m, PrimState m ~ s) => MutBranch s b a -> Ref s b -> (a -> (a, r)) -> m (Maybe r) -- | updateBranch, but forces the result before storing it back in -- the reference. updateBranch' :: (Mutable s a, PrimMonad m, PrimState m ~ s) => MutBranch s b a -> Ref s b -> (a -> (a, r)) -> m (Maybe r) -- | modifyBranch but for a monadic function. Uses copyRef -- into the reference after the action is completed. modifyBranchM :: (Mutable s a, PrimMonad m, PrimState m ~ s) => MutBranch s b a -> Ref s b -> (a -> m a) -> m () -- | modifyBranchM, but forces the result before storing it back in -- the reference. modifyBranchM' :: (Mutable s a, PrimMonad m, PrimState m ~ s) => MutBranch s b a -> Ref s b -> (a -> m a) -> m () -- | updateBranch but for a monadic function. Uses copyRef -- into the reference after the action is completed. updateBranchM :: (Mutable s a, PrimMonad m, PrimState m ~ s) => MutBranch s b a -> Ref s b -> (a -> m (a, r)) -> m (Maybe r) -- | updateBranchM, but forces the result before storing it back in -- the reference. updateBranchM' :: (Mutable s a, PrimMonad m, PrimState m ~ s) => MutBranch s b a -> Ref s b -> (a -> m (a, r)) -> m (Maybe r) -- | Compose two MutBranchs, to drill down on what is being focused. compMB :: MutBranch s a b -> MutBranch s b c -> MutBranch s a c -- | An identity MutBranch, treating the item itself as a whole -- branch. cloneBranch will always "match". idMB :: MutBranch s a a -- | Create a MutBranch for any data type with a Generic -- instance by specifying the constructor name using OverloadedLabels -- --
-- ghci> r <- thawRef (Left 10) -- ghci> freezeBranch (constrMB #_Left) r -- Just 10 -- ghci> freezeBranch (constrMB #_Right) r -- Nothing ---- -- Note that due to limitations in OverloadedLabels, you must prefix the -- constructor name with an undescore. -- -- There also isn't currently any way to utilize OverloadedLabels with -- operator identifiers, so using it with operator constructors (like -- : and []) requires explicit TypeApplications: -- --
-- -- | MutBranch focusing on the cons case of a list -- consMB :: (PrimMonad m, Mutable s a) => MutBranch s [a] (a, [a]) -- consMB = constrMB (CLabel @":") --constrMB :: forall ctor s b a. (Ref s b ~ GRef s b, GMutBranchConstructor ctor s (Rep b) a) => CLabel ctor -> MutBranch s b a -- | A version of Label that removes an underscore at the beginning -- when used with -XOverloadedLabels. Used to specify constructors, since -- labels are currently not able to start with capital letters. data CLabel (ctor :: Symbol) CLabel :: CLabel (ctor :: Symbol) -- | Typeclass powering constrMB using GHC Generics. -- -- Heavily inspired by Data.Generics.Sum.Constructors. class (GMutable s f, Mutable s a) => GMutBranchConstructor (ctor :: Symbol) s f a | ctor f -> a -- | Useful type family to Ref m over every item in a -- type-level list -- --
-- ghci> :kind! MapRef IO '[Int, V.Vector Double] -- '[ MutVar RealWorld Int, MVector RealWorld Double ] --type family MapRef s as -- | MutBranch focusing on the nil case of a list nilMB :: Mutable s a => MutBranch s [a] () -- | MutBranch focusing on the cons case of a list consMB :: Mutable s a => MutBranch s [a] (a, [a]) -- | MutBranch focusing on the Nothing case of a Maybe nothingMB :: Mutable s a => MutBranch s (Maybe a) () -- | MutBranch focusing on the Just case of a Maybe justMB :: Mutable s a => MutBranch s (Maybe a) a -- | MutBranch focusing on the Left case of an Either leftMB :: (Mutable s a, Mutable s b) => MutBranch s (Either a b) a -- | MutBranch focusing on the Right case of an Either rightMB :: (Mutable s a, Mutable s b) => MutBranch s (Either a b) b instance (Data.Mutable.Internal.Mutable s a, Data.Mutable.Branches.GMutBranchSum ctor (Data.Generics.Internal.Families.Has.HasCtorP ctor l) s l r a) => Data.Mutable.Branches.GMutBranchConstructor ctor s (l GHC.Generics.:+: r) a instance (Data.Mutable.Internal.GMutable s r, Data.Mutable.Branches.GMutBranchConstructor ctor s l a, Data.Generics.Product.Internal.HList.GIsList (Data.Mutable.Internal.GRef_ s l) (Data.Mutable.Internal.GRef_ s l) (Data.Mutable.Internal.MapRef s as) (Data.Mutable.Internal.MapRef s as), Data.Generics.Product.Internal.HList.GIsList l l as as, Data.Generics.Product.Internal.HList.ListTuple a a as as, Data.Mutable.Internal.ListRefTuple s b as, Data.Mutable.Internal.Ref s a GHC.Types.~ b) => Data.Mutable.Branches.GMutBranchSum ctor 'GHC.Types.True s l r a instance (Data.Mutable.Internal.GMutable s l, Data.Mutable.Branches.GMutBranchConstructor ctor s r a, Data.Mutable.Internal.Ref s a GHC.Types.~ b) => Data.Mutable.Branches.GMutBranchSum ctor 'GHC.Types.False s l r a instance (Data.Mutable.Internal.GMutable s f, Data.Mutable.Internal.Mutable s a, Data.Generics.Product.Internal.HList.GIsList (Data.Mutable.Internal.GRef_ s f) (Data.Mutable.Internal.GRef_ s f) (Data.Mutable.Internal.MapRef s as) (Data.Mutable.Internal.MapRef s as), Data.Generics.Product.Internal.HList.GIsList f f as as, Data.Generics.Product.Internal.HList.ListTuple a a as as, Data.Mutable.Internal.ListRefTuple s b as, Data.Mutable.Internal.Ref s a GHC.Types.~ b) => Data.Mutable.Branches.GMutBranchConstructor ctor s (GHC.Generics.M1 GHC.Generics.C ('GHC.Generics.MetaCons ctor fixity fields) f) a instance Data.Mutable.Branches.GMutBranchConstructor ctor m f a => Data.Mutable.Branches.GMutBranchConstructor ctor m (GHC.Generics.M1 GHC.Generics.D meta f) a instance (ctor_ GHC.Types.~ GHC.TypeLits.AppendSymbol "_" ctor) => GHC.OverloadedLabels.IsLabel ctor_ (Data.Mutable.Branches.CLabel ctor) -- | Tools for working with individual components of piecewise-mutable -- values. -- -- If Data.Mutable.Branches is for sum types, then -- Data.Mutable.Parts is for sum types. -- -- See https://mutable.jle.im/05-mutable-parts.html for an -- introduction to this module. module Data.Mutable.Parts -- | A MutPart s b a is a way to "zoom into" an a, -- as a part of a mutable reference on b. This allows you to -- only modify a single a part of the b, without -- touching the rest. It's spiritually similar to a Lens' b a. -- -- If MutBranch is for sum types, then MutPart is for -- product types. -- -- See https://mutable.jle.im/05-mutable-parts.html for an -- introduction to this type. -- -- An example that is commonly found in the ecosystem is something like -- (flipped) write :: Int -> MVector s a -> a -> m -- () from Data.Vector.Mutable --- write 3 :: -- MVector s a -> a -> m (), for instance, lets you -- modify a specific part of the vector without touching the rest. -- -- You would use a MutPart using freezePart, -- copyPart, modifyPart, etc. -- -- For non-composite types, there won't really be any meaningful values. -- However, we have them for many composite types. For example, for -- tuples: -- --
-- mutFst :: MutPart s (a, b) a -- mutSnd :: MutPart s (a, b) b ---- --
-- ghci> r <- thawRef (2, 4) -- ghci> copyPart mutFst r 100 -- ghci> freezeRef r -- (100, 4) ---- -- If you are using GRef as an automatically-defined mutable -- reference, then the easiest way to create these for your mutable types -- are with fieldMut and posMut. -- -- If you are using the "Higher-kinded data" pattern, then there's an -- easy way to generate a MutPart for every single field, if you -- have a product type --- see hkdMutParts for more information. newtype MutPart s b a MutPart :: (Ref s b -> Ref s a) -> MutPart s b a [getMutPart] :: MutPart s b a -> Ref s b -> Ref s a -- | Using a MutPart, perform a function on a Ref s -- s as if you had a Ref s a. withPart :: MutPart s b a -> Ref s b -> (Ref s a -> m r) -> m r -- | With a MutPart, read out a specific part of a Ref. freezePart :: (Mutable s a, PrimMonad m, PrimState m ~ s) => MutPart s b a -> Ref s b -> m a -- | With a MutPart, overwrite into a specific part of a Ref. copyPart :: (Mutable s a, PrimMonad m, PrimState m ~ s) => MutPart s b a -> Ref s b -> a -> m () -- | With a MutPart, copy a Ref containing a subvalue into a -- specific part of a larger Ref. -- --
-- data MyType = MT { mtInt :: Int, mtDouble :: Double }
-- deriving Generic
--
-- instance Mutable s MyType where
-- type Ref s MyType = GRef s MyType
--
--
-- -- ghci> x <- thawRef $ MyType 3 4.5 -- ghci> y <- thawRef $ 100 -- ghci> movePartInto (fieldMut #mtInt) x y -- ghci> freezeRef x -- MyType 100 4.5 --movePartInto :: (Mutable s a, PrimMonad m, PrimState m ~ s) => MutPart s b a -> Ref s b -> Ref s a -> m () -- | With a MutPart, copy a specific part of a larger Ref -- into a Ref of the smaller subvalue value. -- --
-- data MyType = MT { mtInt :: Int, mtDouble :: Double }
-- deriving Generic
--
-- instance Mutable s MyType where
-- type Ref s MyType = GRef s MyType
--
--
-- -- ghci> x <- thawRef $ MyType 3 4.5 -- ghci> y <- thawRef $ 100 -- ghci> movePartOver (fieldMut #mtInt) y x -- ghci> freezeRef y -- 3 --movePartOver :: (Mutable s a, PrimMonad m, PrimState m ~ s) => MutPart s b a -> Ref s a -> Ref s b -> m () -- | With a MutPart, copy a specific part of a large Ref into -- that same part in another large Ref. -- --
-- data MyType = MT { mtInt :: Int, mtDouble :: Double }
-- deriving Generic
--
-- instance Mutable s MyType where
-- type Ref s MyType = GRef s MyType
--
--
-- -- ghci> x <- thawRef $ MyType 3 4.5 -- ghci> y <- thawRef $ MyType 100 12.34 -- ghci> movePartWithin (fieldMut #mtInt) x y -- ghci> freezeRef x -- MyType 100 4.5 --movePartWithin :: (Mutable s a, PrimMonad m, PrimState m ~ s) => MutPart s b a -> Ref s b -> Ref s b -> m () -- | Clone out a subvalue of a larger Ref. clonePart :: (Mutable s a, PrimMonad m, PrimState m ~ s) => MutPart s b a -> Ref s b -> m (Ref s a) -- | A non-copying version of unsafeFreezeRef that can be more -- efficient for types where the mutable representation is the same as -- the immutable one (like Vector). -- -- This is safe as long as you never again modify the mutable reference, -- since it can potentially directly mutate the frozen value magically. unsafeFreezePart :: (Mutable s a, PrimMonad m, PrimState m ~ s) => MutPart s b a -> Ref s b -> m a -- | With a MutPart, modify a specific part of a Ref with a -- pure function. modifyPart :: (Mutable s a, PrimMonad m, PrimState m ~ s) => MutPart s b a -> Ref s b -> (a -> a) -> m () -- | modifyPart, but forces the result before storing it back in the -- reference. modifyPart' :: (Mutable s a, PrimMonad m, PrimState m ~ s) => MutPart s b a -> Ref s b -> (a -> a) -> m () -- | updateRef, under a MutPart to only modify a specific -- part of a Ref. updatePart :: (Mutable s a, PrimMonad m, PrimState m ~ s) => MutPart s b a -> Ref s b -> (a -> (a, r)) -> m r -- | updatePart, but forces the result before storing it back in the -- reference. updatePart' :: (Mutable s a, PrimMonad m, PrimState m ~ s) => MutPart s b a -> Ref s b -> (a -> (a, r)) -> m r -- | With a MutPart, modify a specific part of a Ref with a -- monadic function. Uses copyRef into the reference after the -- action is completed. modifyPartM :: (Mutable s a, PrimMonad m, PrimState m ~ s) => MutPart s b a -> Ref s b -> (a -> m a) -> m () -- | modifyPartM, but forces the result before storing it back in -- the reference. modifyPartM' :: (Mutable s a, PrimMonad m, PrimState m ~ s) => MutPart s b a -> Ref s b -> (a -> m a) -> m () -- | updateRefM, under a MutPart to only modify a specific -- part of a Ref. copyRef into the reference after the -- action is completed. updatePartM :: (Mutable s a, PrimMonad m, PrimState m ~ s) => MutPart s b a -> Ref s b -> (a -> m (a, r)) -> m r -- | updatePartM, but forces the result before storing it back in -- the reference. updatePartM' :: (Mutable s a, PrimMonad m, PrimState m ~ s) => MutPart s b a -> Ref s b -> (a -> m (a, r)) -> m r -- | Compose two MutParts one after the other. -- -- Note this is also available (albeit flipped in arguments) through the -- Category instance. compMP :: MutPart s a b -> MutPart s b c -> MutPart s a c infixr 9 `compMP` -- | The identity MutPart: simply focus into the same type itself. -- -- Note this is also available through the Category instance. idMP :: MutPart s a a -- | MutPart into the first field of a tuple reference. mutFst :: MutPart s (a, b) a -- | MutPart into the second field of a tuple reference. mutSnd :: MutPart s (a, b) b -- | Create a MutPart for a field name. Should work for any type -- with one constructor whose mutable reference is GRef. See -- fieldMut for usage directions. -- -- Mostly leverages the power of Data.Generics.Product.Fields. class (Mutable s b, Mutable s a) => FieldMut (fld :: Symbol) s b a | fld b -> a -- | Create a MutPart for a field name. Should work for any type -- with one constructor whose mutable reference is GRef. -- -- Is meant to be used with OverloadedLabels: -- --
-- data MyType = MyType { mtInt :: Int, mtDouble :: Double }
-- deriving (Generic, Show)
--
-- instance Mutable s MyType where
-- type Ref s MyType = GRef s MyType
--
--
-- -- ghci> r <- thawRef (MyType 3 4.5) -- ghci> freezePart (fieldMut #mtInt) r -- 3 -- ghci> copyPart (fieldMut #mtDouble) 1.23 -- ghci> freezeRef r -- MyType 3 1.23 ---- -- However, you can use it without OverloadedLabels by using Label -- with TypeApplications: -- --
-- ghci> freezePart (fieldMut (Label @"mtInt")) r -- 3 ---- -- This and posMut are the main ways to generate a MutPart -- for a type whose mutable reference is GRef. Note that because -- all of the lookups are done at compile-time, fieldMut and -- posMut have more or less identical performance characteristics. fieldMut :: FieldMut fld s b a => Label fld -> MutPart s b a -- | A helpful wrapper over withPart (fieldMut -- #blah). Create a fieldMut and directly use it. withField :: FieldMut fld s b a => Label fld -> Ref s b -> (Ref s a -> m r) -> m r -- | A helpful wrapper around getMutPart (fieldMut -- #blah). Directly use a fieldMut to access a mutable field. mutField :: forall fld s b a. FieldMut fld s b a => Label fld -> Ref s b -> Ref s a -- | Proxy for label type data Label (a :: Symbol) Label :: Label (a :: Symbol) -- | Create a MutPart for a position in a product type. Should work -- for any type with one constructor whose mutable reference is -- GRef. See posMut for usage directions. -- -- Mostly leverages the power of Data.Generics.Product.Positions. class (Mutable s b, Mutable s a) => PosMut (i :: Nat) s b a | i b -> a -- | Create a MutPart for a position in a product type. Should work -- for any type with one constructor whose mutable reference is -- GRef. -- -- Meant to be used with TypeApplications: -- --
-- data MyType = MyType Int Double -- deriving (Generic, Show) -- -- instance Mutable s MyType where -- type Ref s MyType = GRef s MyType ---- --
-- ghci> r <- thawRef (MyType 3 4.5) -- ghci> freezePart (posMut @1) r -- 3 -- ghci> copyPart (posMut @2) 1.23 -- ghci> freezeRef r -- MyType 3 1.23 ---- -- This and fieldMut are the main ways to generate a -- MutPart for a type whose mutable reference is GRef. Note -- that because all of the lookups are done at compile-time, -- posMut and fieldMut have more or less identical -- performance characteristics. posMut :: PosMut i s b a => MutPart s b a -- | A helpful wrapper over withPart (posMut @n). -- Create a posMut and directly use it. withPos :: forall i s m b a r. PosMut i s b a => Ref s b -> (Ref s a -> m r) -> m r -- | A helpful wrapper around getMutPart (posMut -- @n). Directly use a posMut to access a mutable field. mutPos :: forall i s b a. PosMut i s b a => Ref s b -> Ref s a -- | Create a MutPart splitting out a product type into a tuple of -- refs for every field in that product type. Should work for any type -- with one constructor whose mutable reference is GRef. See -- tupleMut for usage directions. -- -- Mostly leverages the power of Data.Generics.Product.HList. class (Mutable s b, Mutable s a) => TupleMut s b a | b -> a -- | Create a MutPart splitting out a product type into a tuple of -- refs for every field in that product type. Should work for any type -- with one constructor whose mutable reference is GRef. -- -- Probably most easily used using withTuple: -- --
-- data MyType = MyType Int Double -- deriving (Generic, Show) -- -- instance Mutable s MyType where -- type Ref s MyType = GRef s MyType ---- -- Now there is an instance of TupleMut m MyType (Int, -- Double). -- --
-- ghci> r <- thawRef (MyType 3 4.5) -- ghci> withTuple r $ (rI, rD) -> do -- .. modifyRef rI negate -- .. modifyRef rD (* 2) -- ghci> freezeRef r -- MyType (-3) 9 ---- -- As can be seen, within the lambda, we can get access to every mutable -- reference inside a MyType reference. -- -- Performance-wise, this appears to be faster than fieldMut and -- posMut when using a single reference, but slower if using all -- references. tupleMut :: TupleMut s b a => MutPart s b a -- | A helpful wrapper over withPart tupleMut. -- Directly operate on the items in the data type, getting the references -- as a tuple. See tupleMut for more details on when this should -- work. -- --
-- data MyType = MyType Int Double -- deriving (Generic, Show) -- -- instance Mutable s MyType where -- type Ref s MyType = GRef s MyType ---- --
-- ghci> r <- thawRef (MyType 3 4.5) -- ghci> withTuple r $ (rI, rD) -> do -- .. modifyRef rI negate -- .. modifyRef rD (* 2) -- ghci> freezeRef r -- MyType (-3) 9 --withTuple :: TupleMut s b a => Ref s b -> (Ref s a -> m r) -> m r -- | If you are using the "higher-kinded data" pattern, a la -- https://reasonablypolymorphic.com/blog/higher-kinded-data/, and -- you have the appropriate instance for Ref, then you can use -- this to generate a MutPart for every field, if you have a type -- with only one constructor. -- --
-- data MyTypeF f = MT
-- { mtInt :: f Int
-- , mtDouble :: f Double
-- }
-- deriving Generic
--
-- instance Mutable (MyTypeF Identity) where
-- type Ref (MyTypeF Identity) = MyTypeF (RefFor m)
--
-- mx :: MutPart s (MyTypeF Identity) (Vector Int)
-- my :: MutPart s (MyTypeF Identity) (Vector Double)
-- MT mx my = hkdMutParts @MyTypeF
--
--
-- -- ghci> r <- thawRef (MT 3 4.5) -- ghci> freezePart mx r -- 3 -- ghci> copyPart (mtDouble (hkdMutParts @MyTypeF)) r 12.3 -- ghci> freezeRef r -- MT 3 12.3 ---- -- Performance-wise, this is about equivalent to fieldMut and -- posMut for the most part, so the main advantage would be purely -- syntactical. If performance is an issue, you should benchmark all the -- different ways just to be sure. As a general rule, it seems like deep -- nested accesses are faster with composition of fieldMut and -- posMut, but immediate shallow access is often faster with -- hkdMutParts...but this probably does vary on a case-by-case -- basis. hkdMutParts :: forall z s. (Generic (z (RefFor s)), Generic (z (MutPart s (z Identity))), HKDMutParts s z (Rep (z (RefFor s))) (Rep (z (MutPart s (z Identity))))) => z (MutPart s (z Identity)) -- | Typeclass used to implement hkdMutParts. See documentation of -- hkdMutParts for more information. class (Mutable s (z Identity), Ref s (z Identity) ~ z (RefFor s)) => HKDMutParts s z i o -- | A MutPart for a field in a vinyl Rec, automatically -- generated as the first field with a matching type. This is polymorphic -- to work over both Rec and ARec. -- --
-- ghci> r <- thawRef $ [1,2,3] :& [True, False] :& RNil -- ghci> modifyPart (mutRec @Bool) r reverse -- ghci> freezeRef r -- [1,2,3] :& [False, True] :& RNil --mutRec :: forall a as f rec s. (Ref s (rec f as) ~ rec (RecRef s f) as, RecElem rec a a as as (RIndex a as), RecElemFCtx rec (RecRef s f)) => MutPart s (rec f as) (f a) -- | A MutPart to get into a CoerceRef. coerceRef :: Ref s b ~ CoerceRef s b a => MutPart s b a -- | Handy wrapper over getMutPart coerceRef. withCoerceRef :: CoerceRef s b a -> (Ref s a -> m r) -> m r -- | Useful type family to Ref m over every item in a -- type-level list -- --
-- ghci> :kind! MapRef IO '[Int, V.Vector Double] -- '[ MutVar RealWorld Int, MVector RealWorld Double ] --type family MapRef s as instance (Data.Mutable.Internal.Mutable s b, Data.Mutable.Internal.Mutable s a, Data.Mutable.Internal.Ref s b GHC.Types.~ Data.Mutable.Internal.GRef s b, gref GHC.Types.~ Data.Mutable.Parts.Fst (Data.Mutable.Parts.Traverse (Data.Mutable.Internal.GRef_ s (Data.Generics.Product.Internal.Positions.CRep b)) 1), GHC.Types.Coercible (Data.Mutable.Internal.GRef_ s (GHC.Generics.Rep b) ()) (gref ()), Data.Generics.Product.Internal.GLens.GLens' (Data.Mutable.Parts.HasTotalPositionPSym i) gref (Data.Mutable.Internal.Ref s a), Data.Generics.Product.Positions.HasPosition' i b a) => Data.Mutable.Parts.PosMut i s b a instance (Data.Mutable.Internal.Mutable s b, Data.Mutable.Internal.Mutable s a, Data.Mutable.Internal.Ref s b GHC.Types.~ Data.Mutable.Internal.GRef s b, Data.Generics.Product.Internal.HList.GIsList (Data.Mutable.Internal.GRef_ s (GHC.Generics.Rep b)) (Data.Mutable.Internal.GRef_ s (GHC.Generics.Rep b)) (Data.Mutable.Internal.MapRef s as) (Data.Mutable.Internal.MapRef s as), Data.Generics.Product.Internal.HList.GIsList (GHC.Generics.Rep b) (GHC.Generics.Rep b) as as, Data.Generics.Product.Internal.HList.ListTuple a a as as, Data.Generics.Product.Internal.HList.ListTuple c c (Data.Mutable.Internal.MapRef s as) (Data.Mutable.Internal.MapRef s as), Data.Mutable.Internal.Ref s a GHC.Types.~ c) => Data.Mutable.Parts.TupleMut s b a instance (Data.Mutable.Internal.Mutable s b, Data.Mutable.Internal.Mutable s a, Data.Mutable.Internal.Ref s b GHC.Types.~ Data.Mutable.Internal.GRef s b, Data.Generics.Product.Internal.GLens.GLens' (Data.Mutable.Parts.HasTotalFieldPSym fld) (Data.Mutable.Internal.GRef_ s (GHC.Generics.Rep b)) (Data.Mutable.Internal.Ref s a), Data.Generics.Product.Fields.HasField' fld b a) => Data.Mutable.Parts.FieldMut fld s b a instance (Data.Mutable.Internal.Mutable s (z Data.Vinyl.Functor.Identity), Data.Mutable.Internal.Ref s (z Data.Vinyl.Functor.Identity) GHC.Types.~ z (Data.Mutable.Internal.RefFor s)) => Data.Mutable.Parts.HKDMutParts s z (GHC.Generics.K1 i (Data.Mutable.Internal.RefFor s c)) (GHC.Generics.K1 i (Data.Mutable.Parts.MutPart s (z Data.Vinyl.Functor.Identity) c)) instance (Data.Mutable.Internal.Mutable s (z Data.Vinyl.Functor.Identity), Data.Mutable.Internal.Ref s (z Data.Vinyl.Functor.Identity) GHC.Types.~ z (Data.Mutable.Internal.RefFor s)) => Data.Mutable.Parts.HKDMutParts s z GHC.Generics.U1 GHC.Generics.U1 instance (Data.Mutable.Internal.Mutable s (z Data.Vinyl.Functor.Identity), Data.Mutable.Internal.Ref s (z Data.Vinyl.Functor.Identity) GHC.Types.~ z (Data.Mutable.Internal.RefFor s), (TypeError ...)) => Data.Mutable.Parts.HKDMutParts s z GHC.Generics.V1 GHC.Generics.V1 instance forall k s (z :: (* -> *) -> *) (i :: k -> *) (o :: k -> *) a (b :: GHC.Generics.Meta). Data.Mutable.Parts.HKDMutParts s z i o => Data.Mutable.Parts.HKDMutParts s z (GHC.Generics.M1 a b i) (GHC.Generics.M1 a b o) instance forall k s (z :: (* -> *) -> *) (i :: k -> *) (o :: k -> *) (i' :: k -> *) (o' :: k -> *). (Data.Mutable.Parts.HKDMutParts s z i o, Data.Mutable.Parts.HKDMutParts s z i' o') => Data.Mutable.Parts.HKDMutParts s z (i GHC.Generics.:*: i') (o GHC.Generics.:*: o') instance forall k s (z :: (* -> *) -> *) (i :: k -> *) (i' :: k -> *) (o :: k -> *). (Data.Mutable.Internal.Mutable s (z Data.Vinyl.Functor.Identity), Data.Mutable.Internal.Ref s (z Data.Vinyl.Functor.Identity) GHC.Types.~ z (Data.Mutable.Internal.RefFor s), (TypeError ...)) => Data.Mutable.Parts.HKDMutParts s z (i GHC.Generics.:+: i') o instance Control.Category.Category (Data.Mutable.Parts.MutPart s) instance Data.Vinyl.XRec.IsoHKD (Data.Mutable.Parts.MutPart s b) a -- | Main entrypoint of the package. Abstract over different types for -- piecewise-mutable references of values. -- -- See https://mutable.jle.im/ for a comprehensive introduction. module Data.Mutable -- | An instance of Mutable s a means that a can -- be stored a mutable reference in a PrimMonad m (where -- s is the mutable state token PrimState of that monad). -- -- The associated type Ref s a links any a to -- the type of its canonical mutable version. -- -- The benefit of this typeclass, instead of just using -- IORef or MutVar or specific mutable versions like -- Vector and MVector, is two-fold: -- --
instance (Mutable s a, Mutable s b) => -- Mutable s (a, b)If a and b are -- piecwise-mutable, then the instance here will appropriately utilize -- that fact.
-- data TwoVectors = TV
-- { tvInt :: Vector Int
-- , tvDouble :: Vector Double
-- }
-- deriving Generic
--
-- instance Mutable s TwoVectors where
-- type Ref s TwoVectors = GRef s TwoVectors
--
--
-- Then now we get:
--
-- -- thawRef :: TwoVectors -> m (GRef s TwoVectors) -- freezeRef :: GRef s TwoVectors -> m TwoVectors ---- -- And GRef s 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 MVectors. 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 -- TwoVectors. 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 -- https://reasonablypolymorphic.com/blog/higher-kinded-data/, -- then we can also do: -- --
-- data TwoVectors f = TV
-- { tvInt :: HKD f (Vector Int)
-- , tvDouble :: HKD f (Vector Double)
-- }
-- deriving Generic
--
-- instance Mutable (TwoVectors Identity) where
-- type Ref (TwoVectors Identity) = TwoVectors (RefFor s)
--
--
-- 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 RealWorld) -- ghci> :t is -- 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 s MyType = CoerceRef s 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 s (MyContainer a) = TraverseRef s MyContainer a ---- -- See https://mutable.jle.im/02-mutable-and-ref.html for more -- information on this typeclass and how to define instances -- automatically, and also -- --
-- type Ref s (Vector a) = MVector s a
--
--
-- This means that using thawRef on a Vector will give you
-- an MVector, using freezeRef on a Vector will give
-- you a Vector, etc.
--
--
-- thawRef
-- :: (PrimMonad m, PrimState m ~ s)
-- => Vector a
-- -> m (Vector s a)
--
-- freezeRef
-- :: (PrimMonad m, PrimState m ~ s)
-- => Vector s a
-- -> m (Vector a)
--
-- copyRef
-- :: (PrimMonad m, PrimState m ~ s)
-- => Vector s a
-- -> Vector a
-- -> m ()
--
--
-- This associated type must be unique for a, so no two types
-- a can have the same Ref s a. This makes type
-- inference a lot more useful: if you use freezeRef on an
-- MVector, for instance, the return type will be inferred to be
-- 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 s a = GRef s 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 s MyType
--
-- -- This is equivalent to the above
-- instance Mutable s MyType
-- type Ref s MyType = MutVar s MyType
--
-- -- any Generic instance
-- data MyType = MyType { mtInt :: Int, mtDouble :: Double }
-- deriving Generic
--
-- instance Mutable s MyType where
-- type Ref s MyType = GRef s MyType
--
--
-- See https://mutable.jle.im/02-mutable-and-ref.html for more
-- information on this type family and how to define instances
-- automatically.
--
-- Note that this type synonym ins injective --- this means that if you
-- write a function polymorphic over Ref s a, you can
-- always infer s and a (the value stored in the
-- Ref).
--
-- In practice, if you want to write your own instance from scratch, the
-- consequence is that you must have the s type variable
-- somewhere in your type (see UnitRef and VoidRef for
-- examples).
type family Ref s a = (v :: Type) | v -> a s;
type Ref s a = MutVar s a;
}
-- | Thaw a pure/persistent value into its mutable version, which
-- can be manipulated using modifyRef or other methods specific
-- for that type (like read).
--
-- Returns the Ref instance, so, for example, for Vector:
--
-- -- thawRef -- :: (PrimMonad m, PrimState m ~ s) -- => Vector a -- -> m (Vector s a) ---- -- For non-composite (like Int), this is often called the "new -- var" function, like newIORef / newSTRef / -- newMutVar etc. thawRef :: (Mutable s a, PrimMonad m, PrimState m ~ s) => a -> m (Ref s 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 Vector: -- --
-- freezeRef -- :: (PrimMonad m, PrimState m ~ s) -- => Vector s a -- -> m (Vector a) ---- -- For non-composite (like Int), this is often called the "read -- var" function, like readIORef / readSTRef / -- readMutVar etc. freezeRef :: (Mutable s a, PrimMonad m, PrimState m ~ s) => Ref s a -> m a -- | Overwrite a mutable value by provivding a pure/persistent value. -- copyRef -- -- Returns the Ref and the value, so, for example, for -- Vector: -- --
-- copyRef -- :: (PrimMonad m, PrimState m ~ s) -- => Vector s a -- -> 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 writeIORef / writeSTRef / -- writeMutVar etc. copyRef :: (Mutable s a, PrimMonad m, PrimState m ~ s) => Ref s a -> a -> 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 :: (Mutable s a, PrimMonad m, PrimState m ~ s) => Ref s a -> Ref s a -> 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 :: (Mutable s a, PrimMonad m, PrimState m ~ s) => Ref s a -> m (Ref s 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 Vector). -- -- This is safe as long as you never again use the original pure value, -- since it can potentially directly mutate it. unsafeThawRef :: (Mutable s a, PrimMonad m, PrimState m ~ s) => a -> m (Ref s 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 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 :: (Mutable s a, PrimMonad m, PrimState m ~ s) => Ref s a -> m a -- | Thaw a pure/persistent value into its mutable version, which -- can be manipulated using modifyRef or other methods specific -- for that type (like read). -- -- Returns the Ref instance, so, for example, for Vector: -- --
-- thawRef -- :: (PrimMonad m, PrimState m ~ s) -- => Vector a -- -> m (Vector s a) ---- -- For non-composite (like Int), this is often called the "new -- var" function, like newIORef / newSTRef / -- newMutVar etc. thawRef :: (Mutable s a, DefaultMutable s a (Ref s a), PrimMonad m, PrimState m ~ s) => a -> m (Ref s 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 Vector: -- --
-- freezeRef -- :: (PrimMonad m, PrimState m ~ s) -- => Vector s a -- -> m (Vector a) ---- -- For non-composite (like Int), this is often called the "read -- var" function, like readIORef / readSTRef / -- readMutVar etc. freezeRef :: (Mutable s a, DefaultMutable s a (Ref s a), PrimMonad m, PrimState m ~ s) => Ref s a -> m a -- | Overwrite a mutable value by provivding a pure/persistent value. -- copyRef -- -- Returns the Ref and the value, so, for example, for -- Vector: -- --
-- copyRef -- :: (PrimMonad m, PrimState m ~ s) -- => Vector s a -- -> 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 writeIORef / writeSTRef / -- writeMutVar etc. copyRef :: (Mutable s a, DefaultMutable s a (Ref s a), PrimMonad m, PrimState m ~ s) => Ref s a -> a -> 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 :: (Mutable s a, DefaultMutable s a (Ref s a), PrimMonad m, PrimState m ~ s) => Ref s a -> Ref s a -> 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 :: (Mutable s a, DefaultMutable s a (Ref s a), PrimMonad m, PrimState m ~ s) => Ref s a -> m (Ref s 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 Vector). -- -- This is safe as long as you never again use the original pure value, -- since it can potentially directly mutate it. unsafeThawRef :: (Mutable s a, DefaultMutable s a (Ref s a), PrimMonad m, PrimState m ~ s) => a -> m (Ref s 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 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 :: (Mutable s a, DefaultMutable s a (Ref s a), PrimMonad m, PrimState m ~ s) => Ref s a -> m a -- | Apply a pure function on an immutable value onto a value stored in a -- mutable reference. modifyRef :: (Mutable s a, PrimMonad m, PrimState m ~ s) => Ref s a -> (a -> a) -> m () -- | modifyRef, but forces the result before storing it back in the -- reference. modifyRef' :: (Mutable s a, PrimMonad m, PrimState m ~ s) => Ref s a -> (a -> a) -> m () -- | Apply a pure function on an immutable value onto a value stored in a -- mutable reference, returning a result value from that function. updateRef :: (Mutable s a, PrimMonad m, PrimState m ~ s) => Ref s a -> (a -> (a, b)) -> m b -- | updateRef, but forces the updated value before storing it back -- in the reference. updateRef' :: (Mutable s a, PrimMonad m, PrimState m ~ s) => Ref s a -> (a -> (a, b)) -> m b -- | A handy newtype wrapper that allows you to partially apply Ref. -- RefFor m a is the same as Ref s a, but -- can be partially applied. -- -- If used with HKD, you can treat this syntactically identically -- as a Ref s a. newtype RefFor s a RefFor :: Ref s a -> RefFor s a [getRefFor] :: RefFor s a -> Ref s a -- | 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 s MyType -- -- -- the above is the same as: -- instance Mutable s MyType -- type Ref s MyType = MutVar s) MyType ---- -- The case for any instance of Generic: -- --
-- instance Mutable s MyType -- type Ref s MyType = GRef s MyType ---- -- The case for the "higher-kinded data" pattern a la -- https://reasonablypolymorphic.com/blog/higher-kinded-data/: -- --
-- instance Mutable s (MyTypeF Identity) -- type Ref s (MyTypeF Identity) = MyTypeF (RefFor s) ---- -- The case for any newtype wrapper: -- --
-- newtype MyType = MT (Vector Double) -- -- instance Mutable s MyType where -- type Ref s MyType = CoerceRef s 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 s a => Mutable s (MyContainer a) where -- type Ref s (MyContainer a) = TraverseRef s MyContainer a --class DefaultMutable s a r | r -> a s -- | 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 s MyType where
-- type Ref s MyType = GRef s MyType
--
--
-- -- ghci> r <- thawRef (MyType 3 4.5) -- ghci> freezeRef r -- MyType 3 4.5 -- ghci> freezePart (fieldMut #mtInt) r -- 3 -- ghci> 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. data GRef s a -- | A MutVar behaves like a single-element mutable array associated -- with a primitive state token. data MutVar s a -- | 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 (Vector Double) -- -- instance Mutable s MyVec where -- type Ref s MyVec = CoerceRef s s (Vector Double) ---- -- The Ref s MyVec uses the a MVector Double -- under the hood. -- -- It's essentially a special case of GRef for newtypes. newtype CoerceRef s b a CoerceRef :: Ref s a -> CoerceRef s b a [getCoerceRef] :: CoerceRef s b a -> Ref s a -- | 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: -- --
-- 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 s f a TraverseRef :: f (Ref s a) -> TraverseRef s f a [getTraverseRef] :: TraverseRef s f a -> f (Ref s a) -- | A Ref for instances of GMutable, which are the -- GHC.Generics combinators. newtype GMutableRef s f a GMutableRef :: GRef_ s f a -> GMutableRef s f a [getGMutableRef] :: GMutableRef s f a -> GRef_ s f a -- | Ref for components in a vinyl Rec. newtype RecRef s f a RecRef :: Ref s (f a) -> RecRef s f a [getRecRef] :: RecRef s f a -> Ref s (f a) -- | The mutable reference of the HList type from generic-lens. data HListRef :: Type -> [Type] -> Type [NilRef] :: HListRef s '[] [:!>] :: Ref s a -> HListRef s as -> HListRef s (a : as) infixr 5 :!> -- | The Ref for () (unit). This breaks the pattern for -- tuple instances (type Ref s (a, b) = (Ref s a, -- Ref s b)), but is necessary for type inference (see -- documentation for Ref). data UnitRef s UnitRef :: UnitRef s -- | The Ref for Void. data VoidRef s -- | Newtype wrapper that can provide any type with a Mutable -- instance, giving it a "non-piecewise" instance. Can be useful for -- avoiding orphan instances yet still utilizing auto-deriving features, -- or for overwriting the Mutable instance of other instances. -- -- For example, let's say you want to auto-derive an instance for your -- data type: -- --
-- data MyType = MT Int Double OtherType -- deriving Generic ---- -- This is possible if all of MyTypes fields have Mutable -- instances. However, let's say OtherType comes from an -- external library that you don't have control over, and so you cannot -- give it a Mutable instance without incurring an orphan -- instance. -- -- One solution is to wrap it in VarMut: -- --
-- data MyType = MT Int Double (VarMut OtherType) -- deriving Generic ---- -- This can then be auto-derived: -- --
-- instance Mutable s MyType where -- type Ref s MyType = GRef s MyType ---- -- It can also be used to override a Mutable instance. For -- example, even if the Mutable instance of SomeType is -- piecewise-mutable, the Mutable instance of VarMut -- SomeType will be not be piecewise. -- -- For example, the Mutable instance for String is a -- mutable linked list, but it might be more efficient to treat it as an -- atomic value to update all at once. You can use VarMut -- String to get that Mutable instance. newtype VarMut a VarMut :: a -> VarMut a [getVarMut] :: VarMut a -> a -- | Similar to VarMut, this allows you to overwrite the normal -- Mutable instance of a type to utilize a coercible type's -- Mutable instance instead of its normal instance. It's also -- useful to provide an instance for an externally defined type without -- incurring orphan instances. -- -- For example, if an external library provides -- --
-- newtype DoubleVec = DV (Vector Double) ---- -- and you want to use it following Vectors Mutable -- instance (via MVector), but you don't want to write an orphan -- instance like -- --
-- instance Mutable s DoubleVec where -- type Ref s DoubleVec = CoerceRef s DoubleVec (Vector Double) ---- -- then you can instead use CoerceMut DoubleVec (Vector -- Double) as the data type. This wrapped type does use the -- inderlying Mutable insatnce for Vector. newtype CoerceMut s a CoerceMut :: s -> CoerceMut s a [getCoerceMut] :: CoerceMut s a -> s -- | Similar to VarMut, this allows you to overwrite the normal -- Mutable instance for a type to utilize its Traversable -- instance instead of its normal instance. It's also useful to provide -- an instance for an externally defined type without incurring orphan -- instances. -- -- For example, the instance of Mutable (TraverseMut [] -- a) is a normal list of mutable references, instead of a full-on -- mutable linked list. newtype TraverseMut f a TraverseMut :: f a -> TraverseMut f a [getTraverseMut] :: TraverseMut f a -> f a -- | Similar to VarMut, this allows you to overwrite the normal -- Mutable instance of a type to make it immutable. -- -- For example, let's say you have a type, with the automatically derived -- generic instance of Mutable: -- --
-- data MyType = MT
-- { mtX :: Int
-- , mtY :: Vector Double
-- , mtZ :: String
-- }
-- deriving Generic
--
-- instance Mutable s MyType where
-- type Ref s MyType = GRef s MyType
--
--
-- This basically uses three mutable references: the Int, the
-- Vector Double, and the String. However, you
-- might want the Mutable instance of MyType to be
-- immutable String field, and so it cannot be updated at
-- all even when thawed. To do that, you can instead have:
--
--
-- data MyType = MT
-- { mtX :: Int
-- , mtY :: Vector Double
-- , mtZ :: Immutable String
-- }
-- deriving Generic
--
-- instance Mutable s MyType where
-- type Ref s MyType = GRef s MyType
--
--
-- which has that behavior. The Int and the Vector will be
-- mutable within Ref s MyType, but not the
-- String.
newtype Immutable s a
Immutable :: a -> Immutable s a
[getImmutable] :: Immutable s a -> a
-- | A MutPart s b a is a way to "zoom into" an a,
-- as a part of a mutable reference on b. This allows you to
-- only modify a single a part of the b, without
-- touching the rest. It's spiritually similar to a Lens' b a.
--
-- If MutBranch is for sum types, then MutPart is for
-- product types.
--
-- See https://mutable.jle.im/05-mutable-parts.html for an
-- introduction to this type.
--
-- An example that is commonly found in the ecosystem is something like
-- (flipped) write :: Int -> MVector s a -> a -> m
-- () from Data.Vector.Mutable --- write 3 ::
-- MVector s a -> a -> m (), for instance, lets you
-- modify a specific part of the vector without touching the rest.
--
-- You would use a MutPart using freezePart,
-- copyPart, modifyPart, etc.
--
-- For non-composite types, there won't really be any meaningful values.
-- However, we have them for many composite types. For example, for
-- tuples:
--
-- -- mutFst :: MutPart s (a, b) a -- mutSnd :: MutPart s (a, b) b ---- --
-- ghci> r <- thawRef (2, 4) -- ghci> copyPart mutFst r 100 -- ghci> freezeRef r -- (100, 4) ---- -- If you are using GRef as an automatically-defined mutable -- reference, then the easiest way to create these for your mutable types -- are with fieldMut and posMut. -- -- If you are using the "Higher-kinded data" pattern, then there's an -- easy way to generate a MutPart for every single field, if you -- have a product type --- see hkdMutParts for more information. newtype MutPart s b a MutPart :: (Ref s b -> Ref s a) -> MutPart s b a [getMutPart] :: MutPart s b a -> Ref s b -> Ref s a -- | Using a MutPart, perform a function on a Ref s -- s as if you had a Ref s a. withPart :: MutPart s b a -> Ref s b -> (Ref s a -> m r) -> m r -- | With a MutPart, read out a specific part of a Ref. freezePart :: (Mutable s a, PrimMonad m, PrimState m ~ s) => MutPart s b a -> Ref s b -> m a -- | With a MutPart, overwrite into a specific part of a Ref. copyPart :: (Mutable s a, PrimMonad m, PrimState m ~ s) => MutPart s b a -> Ref s b -> a -> m () -- | With a MutPart, copy a Ref containing a subvalue into a -- specific part of a larger Ref. -- --
-- data MyType = MT { mtInt :: Int, mtDouble :: Double }
-- deriving Generic
--
-- instance Mutable s MyType where
-- type Ref s MyType = GRef s MyType
--
--
-- -- ghci> x <- thawRef $ MyType 3 4.5 -- ghci> y <- thawRef $ 100 -- ghci> movePartInto (fieldMut #mtInt) x y -- ghci> freezeRef x -- MyType 100 4.5 --movePartInto :: (Mutable s a, PrimMonad m, PrimState m ~ s) => MutPart s b a -> Ref s b -> Ref s a -> m () -- | With a MutPart, copy a specific part of a larger Ref -- into a Ref of the smaller subvalue value. -- --
-- data MyType = MT { mtInt :: Int, mtDouble :: Double }
-- deriving Generic
--
-- instance Mutable s MyType where
-- type Ref s MyType = GRef s MyType
--
--
-- -- ghci> x <- thawRef $ MyType 3 4.5 -- ghci> y <- thawRef $ 100 -- ghci> movePartOver (fieldMut #mtInt) y x -- ghci> freezeRef y -- 3 --movePartOver :: (Mutable s a, PrimMonad m, PrimState m ~ s) => MutPart s b a -> Ref s a -> Ref s b -> m () -- | With a MutPart, copy a specific part of a large Ref into -- that same part in another large Ref. -- --
-- data MyType = MT { mtInt :: Int, mtDouble :: Double }
-- deriving Generic
--
-- instance Mutable s MyType where
-- type Ref s MyType = GRef s MyType
--
--
-- -- ghci> x <- thawRef $ MyType 3 4.5 -- ghci> y <- thawRef $ MyType 100 12.34 -- ghci> movePartWithin (fieldMut #mtInt) x y -- ghci> freezeRef x -- MyType 100 4.5 --movePartWithin :: (Mutable s a, PrimMonad m, PrimState m ~ s) => MutPart s b a -> Ref s b -> Ref s b -> m () -- | Clone out a subvalue of a larger Ref. clonePart :: (Mutable s a, PrimMonad m, PrimState m ~ s) => MutPart s b a -> Ref s b -> m (Ref s a) -- | A non-copying version of unsafeFreezeRef that can be more -- efficient for types where the mutable representation is the same as -- the immutable one (like Vector). -- -- This is safe as long as you never again modify the mutable reference, -- since it can potentially directly mutate the frozen value magically. unsafeFreezePart :: (Mutable s a, PrimMonad m, PrimState m ~ s) => MutPart s b a -> Ref s b -> m a -- | With a MutPart, modify a specific part of a Ref with a -- pure function. modifyPart :: (Mutable s a, PrimMonad m, PrimState m ~ s) => MutPart s b a -> Ref s b -> (a -> a) -> m () -- | modifyPart, but forces the result before storing it back in the -- reference. modifyPart' :: (Mutable s a, PrimMonad m, PrimState m ~ s) => MutPart s b a -> Ref s b -> (a -> a) -> m () -- | updateRef, under a MutPart to only modify a specific -- part of a Ref. updatePart :: (Mutable s a, PrimMonad m, PrimState m ~ s) => MutPart s b a -> Ref s b -> (a -> (a, r)) -> m r -- | updatePart, but forces the result before storing it back in the -- reference. updatePart' :: (Mutable s a, PrimMonad m, PrimState m ~ s) => MutPart s b a -> Ref s b -> (a -> (a, r)) -> m r -- | Create a MutPart for a field name. Should work for any type -- with one constructor whose mutable reference is GRef. See -- fieldMut for usage directions. -- -- Mostly leverages the power of Data.Generics.Product.Fields. class (Mutable s b, Mutable s a) => FieldMut (fld :: Symbol) s b a | fld b -> a -- | Create a MutPart for a field name. Should work for any type -- with one constructor whose mutable reference is GRef. -- -- Is meant to be used with OverloadedLabels: -- --
-- data MyType = MyType { mtInt :: Int, mtDouble :: Double }
-- deriving (Generic, Show)
--
-- instance Mutable s MyType where
-- type Ref s MyType = GRef s MyType
--
--
-- -- ghci> r <- thawRef (MyType 3 4.5) -- ghci> freezePart (fieldMut #mtInt) r -- 3 -- ghci> copyPart (fieldMut #mtDouble) 1.23 -- ghci> freezeRef r -- MyType 3 1.23 ---- -- However, you can use it without OverloadedLabels by using Label -- with TypeApplications: -- --
-- ghci> freezePart (fieldMut (Label @"mtInt")) r -- 3 ---- -- This and posMut are the main ways to generate a MutPart -- for a type whose mutable reference is GRef. Note that because -- all of the lookups are done at compile-time, fieldMut and -- posMut have more or less identical performance characteristics. fieldMut :: FieldMut fld s b a => Label fld -> MutPart s b a -- | A helpful wrapper over withPart (fieldMut -- #blah). Create a fieldMut and directly use it. withField :: FieldMut fld s b a => Label fld -> Ref s b -> (Ref s a -> m r) -> m r -- | A helpful wrapper around getMutPart (fieldMut -- #blah). Directly use a fieldMut to access a mutable field. mutField :: forall fld s b a. FieldMut fld s b a => Label fld -> Ref s b -> Ref s a -- | Proxy for label type data Label (a :: Symbol) Label :: Label (a :: Symbol) -- | Create a MutPart for a position in a product type. Should work -- for any type with one constructor whose mutable reference is -- GRef. See posMut for usage directions. -- -- Mostly leverages the power of Data.Generics.Product.Positions. class (Mutable s b, Mutable s a) => PosMut (i :: Nat) s b a | i b -> a -- | Create a MutPart for a position in a product type. Should work -- for any type with one constructor whose mutable reference is -- GRef. -- -- Meant to be used with TypeApplications: -- --
-- data MyType = MyType Int Double -- deriving (Generic, Show) -- -- instance Mutable s MyType where -- type Ref s MyType = GRef s MyType ---- --
-- ghci> r <- thawRef (MyType 3 4.5) -- ghci> freezePart (posMut @1) r -- 3 -- ghci> copyPart (posMut @2) 1.23 -- ghci> freezeRef r -- MyType 3 1.23 ---- -- This and fieldMut are the main ways to generate a -- MutPart for a type whose mutable reference is GRef. Note -- that because all of the lookups are done at compile-time, -- posMut and fieldMut have more or less identical -- performance characteristics. posMut :: PosMut i s b a => MutPart s b a -- | A helpful wrapper over withPart (posMut @n). -- Create a posMut and directly use it. withPos :: forall i s m b a r. PosMut i s b a => Ref s b -> (Ref s a -> m r) -> m r -- | A helpful wrapper around getMutPart (posMut -- @n). Directly use a posMut to access a mutable field. mutPos :: forall i s b a. PosMut i s b a => Ref s b -> Ref s a -- | Create a MutPart splitting out a product type into a tuple of -- refs for every field in that product type. Should work for any type -- with one constructor whose mutable reference is GRef. See -- tupleMut for usage directions. -- -- Mostly leverages the power of Data.Generics.Product.HList. class (Mutable s b, Mutable s a) => TupleMut s b a | b -> a -- | Create a MutPart splitting out a product type into a tuple of -- refs for every field in that product type. Should work for any type -- with one constructor whose mutable reference is GRef. -- -- Probably most easily used using withTuple: -- --
-- data MyType = MyType Int Double -- deriving (Generic, Show) -- -- instance Mutable s MyType where -- type Ref s MyType = GRef s MyType ---- -- Now there is an instance of TupleMut m MyType (Int, -- Double). -- --
-- ghci> r <- thawRef (MyType 3 4.5) -- ghci> withTuple r $ (rI, rD) -> do -- .. modifyRef rI negate -- .. modifyRef rD (* 2) -- ghci> freezeRef r -- MyType (-3) 9 ---- -- As can be seen, within the lambda, we can get access to every mutable -- reference inside a MyType reference. -- -- Performance-wise, this appears to be faster than fieldMut and -- posMut when using a single reference, but slower if using all -- references. tupleMut :: TupleMut s b a => MutPart s b a -- | A helpful wrapper over withPart tupleMut. -- Directly operate on the items in the data type, getting the references -- as a tuple. See tupleMut for more details on when this should -- work. -- --
-- data MyType = MyType Int Double -- deriving (Generic, Show) -- -- instance Mutable s MyType where -- type Ref s MyType = GRef s MyType ---- --
-- ghci> r <- thawRef (MyType 3 4.5) -- ghci> withTuple r $ (rI, rD) -> do -- .. modifyRef rI negate -- .. modifyRef rD (* 2) -- ghci> freezeRef r -- MyType (-3) 9 --withTuple :: TupleMut s b a => Ref s b -> (Ref s a -> m r) -> m r -- | If you are using the "higher-kinded data" pattern, a la -- https://reasonablypolymorphic.com/blog/higher-kinded-data/, and -- you have the appropriate instance for Ref, then you can use -- this to generate a MutPart for every field, if you have a type -- with only one constructor. -- --
-- data MyTypeF f = MT
-- { mtInt :: f Int
-- , mtDouble :: f Double
-- }
-- deriving Generic
--
-- instance Mutable (MyTypeF Identity) where
-- type Ref (MyTypeF Identity) = MyTypeF (RefFor m)
--
-- mx :: MutPart s (MyTypeF Identity) (Vector Int)
-- my :: MutPart s (MyTypeF Identity) (Vector Double)
-- MT mx my = hkdMutParts @MyTypeF
--
--
-- -- ghci> r <- thawRef (MT 3 4.5) -- ghci> freezePart mx r -- 3 -- ghci> copyPart (mtDouble (hkdMutParts @MyTypeF)) r 12.3 -- ghci> freezeRef r -- MT 3 12.3 ---- -- Performance-wise, this is about equivalent to fieldMut and -- posMut for the most part, so the main advantage would be purely -- syntactical. If performance is an issue, you should benchmark all the -- different ways just to be sure. As a general rule, it seems like deep -- nested accesses are faster with composition of fieldMut and -- posMut, but immediate shallow access is often faster with -- hkdMutParts...but this probably does vary on a case-by-case -- basis. hkdMutParts :: forall z s. (Generic (z (RefFor s)), Generic (z (MutPart s (z Identity))), HKDMutParts s z (Rep (z (RefFor s))) (Rep (z (MutPart s (z Identity))))) => z (MutPart s (z Identity)) -- | Typeclass used to implement hkdMutParts. See documentation of -- hkdMutParts for more information. class (Mutable s (z Identity), Ref s (z Identity) ~ z (RefFor s)) => HKDMutParts s z i o -- | MutPart into the first field of a tuple reference. mutFst :: MutPart s (a, b) a -- | MutPart into the second field of a tuple reference. mutSnd :: MutPart s (a, b) b -- | A MutPart for a field in a vinyl Rec, automatically -- generated as the first field with a matching type. This is polymorphic -- to work over both Rec and ARec. -- --
-- ghci> r <- thawRef $ [1,2,3] :& [True, False] :& RNil -- ghci> modifyPart (mutRec @Bool) r reverse -- ghci> freezeRef r -- [1,2,3] :& [False, True] :& RNil --mutRec :: forall a as f rec s. (Ref s (rec f as) ~ rec (RecRef s f) as, RecElem rec a a as as (RIndex a as), RecElemFCtx rec (RecRef s f)) => MutPart s (rec f as) (f a) -- | A MutPart to get into a CoerceRef. coerceRef :: Ref s b ~ CoerceRef s b a => MutPart s b a -- | Handy wrapper over getMutPart coerceRef. withCoerceRef :: CoerceRef s b a -> (Ref s a -> m r) -> m r -- | A MutBranch s b a represents the information that -- b could potentially be an a. Similar in spirit to a -- Prism' b a. -- -- MutBranch s b a means that a is one potential -- option that b could be in, or that b is a sum type -- and a is one of the branches/constructors. -- -- See https://mutable.jle.im/06-mutable-branches.html for an -- introduction to this module. -- -- If MutPart is for product types, then MutBranch is for -- sum types. -- -- In this case, "branch" means "potential option". For example, the -- branches of Either are Left and Right. -- -- The simplest way to make these is by using constrMB. For -- instance, to get the two branches of an Either: -- --
-- constrMB #_Left :: MutBranch s (Either a b) a -- constrMB #_Right :: MutBranch s (Either a b) b ---- --
-- ghci> r <- thawRef (Left 10) -- ghci> freezeBranch (constrMB #_Left) r -- Just 10 -- ghci> freezeBranch (constrMB #_Right) r -- Nothing ---- -- It uses OverloadedLabels, but requires an underscore before the -- constructor name due to limitations in the extension. -- -- One nice way to use these is with withBranch_: -- --
-- ghci> r <- thawRef (Just 10) -- ghci> withBranch_ (constrMB #_Just) $ i -> -- i is an Int ref -- .. modifyRef i (+ 1) -- ghci> freezeRef r -- Just 11 ---- --
-- ghci> r <- thawRef Nothing -- ghci> withBranch_ (constrMB #_Just) $ i -> -- i is an Int ref -- .. modifyRef i (+ 1) -- ghci> freezeRef r -- Nothing ---- -- Perhaps the most useful usage of this abstraction is for recursive -- data types. -- --
-- data List a = Nil | Cons a (List a) -- deriving Generic -- -- instance Mutable s a => Mutable s (List a) where -- type Ref s (List a) = GRef s (List a) ---- -- GRef s (List a) is now a mutable linked list! Once we -- make the MutBranch for the nil and cons cases: -- --
-- nilBranch :: MutBranch s (List a) () -- nilBranch = constrMB #_Nil -- -- consBranch :: MutBranch s (List a) (a, List a) -- consBranch = constrMB #_Cons ---- -- Here is a function to check if a linked list is currently empty: -- --
-- isEmpty -- :: (PrimMonad m, Mutable s a) -- => Ref s (List a) -- -> m Bool -- isEmpty = hasBranch nilBranch ---- -- Here is one to "pop" a mutable linked list, giving us the first value -- and shifting the rest of the list up. -- --
-- popStack -- :: (PrimMonad m, Mutable s a) -- => Ref s (List a) -- -> m (Maybe a) -- popStack r = do -- c <- projectBranch consBranch r -- case c of -- Nothing -> pure Nothing -- Just (x, xs) -> do -- moveRef r xs -- Just $ freezeRef x ---- -- And here is a function to concatenate a second linked list to the end -- of a first one. -- --
-- concatLists -- :: (PrimMonad m, Mutable s a) -- => Ref s (List a) -- -> Ref s (List a) -- -> m () -- concatLists l1 l2 = do -- c <- projectBranch consBranch l1 -- case c of -- Nothing -> moveRef l1 l2 -- Just (_, xs) -> concatLists xs l2 --data MutBranch s b a MutBranch :: (forall m. (PrimMonad m, PrimState m ~ s) => Ref s b -> m (Maybe (Ref s a))) -> (forall m. (PrimMonad m, PrimState m ~ s) => Ref s a -> m (Ref s b)) -> MutBranch s b a -- | With a MutBranch, attempt to get the mutable contents of a -- branch of a mutable s, if possible. -- --
-- ghci> r <- thawRef (Left 10) -- ghci> s <- projectBranch (constrMB #_Left) r -- ghci> case s of Just s' -> freezeRef s' -- 10 ---- --
-- ghci> r <- thawRef (Right True) -- ghci> s <- projectBranch (constrMB #_Left) r -- ghci> case s of Nothing -> "it was Right" -- "it was Right" --[projectBranch] :: MutBranch s b a -> forall m. (PrimMonad m, PrimState m ~ s) => Ref s b -> m (Maybe (Ref s a)) -- | Embed an a ref as a part of a larger s ref. Note -- that this does not copy or clone: any mutations to the -- a ref will be reflected in the s ref, as long as the -- s ref maintains the reference. -- --
-- ghci> r <- thawRef 100 -- ghci> s <- embedBranch (constMB #_Left) r -- ghci> freezeRef s -- Left 100 -- ghci> modifyRef r (+ 1) -- ghci> freezeRef s -- Left 101 ---- -- Any mutations on s (as long as they keep the same branch) -- will also affect a: -- --
-- ghci> copyRef s (Left 0) -- ghci> freezeRef r -- 0 ---- -- However, "switching branches" on an Either ref will cause it to -- loose the original reference: -- --
-- ghci> copyRef s (Right True) -- ghci> copyRef s (Left 999) -- ghci> freezeRef r -- 0 --[embedBranch] :: MutBranch s b a -> forall m. (PrimMonad m, PrimState m ~ s) => Ref s a -> m (Ref s b) -- | With a MutBranch, thaw an a into a mutable s -- on that branch. -- --
-- ghci> r <- thawBranch (constrMB #_Left) 10 -- ghci> freezeRef r -- Left 10 --thawBranch :: (Mutable s a, PrimMonad m, PrimState m ~ s) => MutBranch s b a -> a -> m (Ref s b) -- | With a MutBranch, read out a specific a branch of an -- s, if it exists. -- --
-- ghci> r <- thawRef (Left 10) -- ghci> freezeBranch (constrMB #_Left) r -- Just 10 -- ghci> freezeBranch (constrMB #_Right) r -- Nothing --freezeBranch :: (Mutable s a, PrimMonad m, PrimState m ~ s) => MutBranch s b a -> Ref s b -> m (Maybe a) -- | With a MutBranch, overwrite an s as an a, on -- that branch. -- --
-- ghci> r <- thawRef (Left 10) -- ghci> s <- thawRef 100 -- ghci> moveBranch (constrMB #_Left) r s -- ghci> freezeRef r -- Left 100 -- ghci> t <- thawRef True -- ghci> moveBranch (constrMB #_Right) r t -- ghci> freezeRef r -- Right True --moveBranch :: (Mutable s b, PrimMonad m, PrimState m ~ s) => MutBranch s b a -> Ref s b -> Ref s a -> m () -- | With a MutBranch, set s to have the branch -- a. -- --
-- ghci> r <- thawRef (Left 10) -- ghci> copyBranch (constrMB #_Left) r 5678 -- ghci> freezeRef r -- Left 5678 -- ghci> copyBranch (constrMB #_Right) r True -- ghci> freezeRef r -- Right True --copyBranch :: (Mutable s b, Mutable s a, PrimMonad m, PrimState m ~ s) => MutBranch s b a -> Ref s b -> a -> m () -- | With a MutBranch, attempt to clone out a branch of a mutable -- s, if possible. -- --
-- ghci> r <- thawRef (Left 10) -- ghci> s <- cloneBranch (constrMB #_Left) -- ghci> case s of Just s' -> freezeRef s' -- 10 ---- --
-- ghci> r <- thawRef (Right True) -- ghci> s <- cloneBranch (constrMB #_Left) -- ghci> case s of Nothing -> "it was Right" -- "it was Right" --cloneBranch :: (Mutable s a, PrimMonad m, PrimState m ~ s) => MutBranch s b a -> Ref s b -> m (Maybe (Ref s a)) -- | Check if an s is currently a certain branch a. hasBranch :: (PrimMonad m, PrimState m ~ s) => MutBranch s b a -> Ref s b -> m Bool -- | Check if an s is not currently a certain branch -- a. hasn'tBranch :: (PrimMonad m, PrimState m ~ s) => MutBranch s b a -> Ref s b -> m Bool -- | A non-copying version of thawBranch that can be more efficient -- for types where the mutable representation is the same as the -- immutable one (like Vector). -- -- This is safe as long as you never again use the original pure value, -- since it can potentially directly mutate it. unsafeThawBranch :: (Mutable s a, PrimMonad m, PrimState m ~ s) => MutBranch s b a -> a -> m (Ref s b) -- | A non-copying version of freezeBranch that can be more -- efficient for types where the mutable representation is the same as -- the immutable one (like Vector). -- -- This is safe as long as you never again modify the mutable reference, -- since it can potentially directly mutate the frozen value magically. unsafeFreezeBranch :: (Mutable s a, PrimMonad m, PrimState m ~ s) => MutBranch s b a -> Ref s b -> m (Maybe a) -- | With a MutBranch, if an s is on the a branch, -- perform an action on the a reference and overwrite the -- s with the modified a. Returns the result of the -- action, if a was found. -- --
-- ghci> r <- thawRef (Just 10) -- ghci> withBranch_ (constrMB #_Just) $ i -> -- i is an Int ref -- .. modifyRef i (+ 1) -- ghci> freezeRef r -- Just 11 ---- --
-- ghci> r <- thawRef Nothing -- ghci> withBranch_ (constrMB #_Just) $ i -> -- i is an Int ref -- .. modifyRef i (+ 1) -- ghci> freezeRef r -- Nothing --withBranch :: (PrimMonad m, PrimState m ~ s) => MutBranch s b a -> Ref s b -> (Ref s a -> m r) -> m (Maybe r) -- | withBranch, but discarding the returned value. withBranch_ :: (PrimMonad m, PrimState m ~ s) => MutBranch s b a -> Ref s b -> (Ref s a -> m r) -> m () -- | With a MutBranch, run a pure function over a potential branch -- a of s. If s is not on that branch, leaves -- s unchanged. -- --
-- ghci> r <- thawRef (Just 10) -- ghci> modifyBranch (constrMB #_Just) r (+ 1) -- ghci> freezeRef r -- Just 11 ---- --
-- ghci> r <- thawRef Nothing -- ghci> modifyBranch (constrMB #_Just) r (+ 1) -- ghci> freezeRef r -- Nothing --modifyBranch :: (Mutable s a, PrimMonad m, PrimState m ~ s) => MutBranch s b a -> Ref s b -> (a -> a) -> m () -- | modifyBranch, but forces the result before storing it back in -- the reference. modifyBranch' :: (Mutable s a, PrimMonad m, PrimState m ~ s) => MutBranch s b a -> Ref s b -> (a -> a) -> m () -- | With a MutBranch, run a pure function over a potential branch -- a of s. The function returns the updated a -- and also an output value to observe. If s is not on that -- branch, leaves s unchanged. -- --
-- ghci> r <- thawRef (Just 10) -- ghci> updateBranch (constrMB #_Just) r $ i -> (i + 1, show i) -- Just "10" -- ghci> freezeRef r -- Just 11 ---- --
-- ghci> r <- thawRef Nothing -- ghci> updateBranch (constrMB #_Just) r $ i -> (i + 1, show i) -- Nothing -- ghci> freezeRef r -- Nothing --updateBranch :: (Mutable s a, PrimMonad m, PrimState m ~ s) => MutBranch s b a -> Ref s b -> (a -> (a, r)) -> m (Maybe r) -- | updateBranch, but forces the result before storing it back in -- the reference. updateBranch' :: (Mutable s a, PrimMonad m, PrimState m ~ s) => MutBranch s b a -> Ref s b -> (a -> (a, r)) -> m (Maybe r) -- | Create a MutBranch for any data type with a Generic -- instance by specifying the constructor name using OverloadedLabels -- --
-- ghci> r <- thawRef (Left 10) -- ghci> freezeBranch (constrMB #_Left) r -- Just 10 -- ghci> freezeBranch (constrMB #_Right) r -- Nothing ---- -- Note that due to limitations in OverloadedLabels, you must prefix the -- constructor name with an undescore. -- -- There also isn't currently any way to utilize OverloadedLabels with -- operator identifiers, so using it with operator constructors (like -- : and []) requires explicit TypeApplications: -- --
-- -- | MutBranch focusing on the cons case of a list -- consMB :: (PrimMonad m, Mutable s a) => MutBranch s [a] (a, [a]) -- consMB = constrMB (CLabel @":") --constrMB :: forall ctor s b a. (Ref s b ~ GRef s b, GMutBranchConstructor ctor s (Rep b) a) => CLabel ctor -> MutBranch s b a -- | A version of Label that removes an underscore at the beginning -- when used with -XOverloadedLabels. Used to specify constructors, since -- labels are currently not able to start with capital letters. data CLabel (ctor :: Symbol) CLabel :: CLabel (ctor :: Symbol) -- | Typeclass powering constrMB using GHC Generics. -- -- Heavily inspired by Data.Generics.Sum.Constructors. class (GMutable s f, Mutable s a) => GMutBranchConstructor (ctor :: Symbol) s f a | ctor f -> a -- | Useful type family to Ref m over every item in a -- type-level list -- --
-- ghci> :kind! MapRef IO '[Int, V.Vector Double] -- '[ MutVar RealWorld Int, MVector RealWorld Double ] --type family MapRef s as -- | MutBranch focusing on the nil case of a list nilMB :: Mutable s a => MutBranch s [a] () -- | MutBranch focusing on the cons case of a list consMB :: Mutable s a => MutBranch s [a] (a, [a]) -- | MutBranch focusing on the Nothing case of a Maybe nothingMB :: Mutable s a => MutBranch s (Maybe a) () -- | MutBranch focusing on the Just case of a Maybe justMB :: Mutable s a => MutBranch s (Maybe a) a -- | MutBranch focusing on the Left case of an Either leftMB :: (Mutable s a, Mutable s b) => MutBranch s (Either a b) a -- | MutBranch focusing on the Right case of an Either rightMB :: (Mutable s a, Mutable s b) => MutBranch s (Either a b) b -- | Class of monads which can perform primitive state-transformer actions class Monad m => PrimMonad (m :: Type -> Type) -- | State token type type family PrimState (m :: Type -> Type)