Copyright  (c) Justin Le 2020 

License  BSD3 
Maintainer  justin@jle.im 
Stability  experimental 
Portability  nonportable 
Safe Haskell  None 
Language  Haskell2010 
Synopsis
 class Monad m => Mutable m a where
 copyRefWhole :: Mutable m a => Ref m a > a > m ()
 moveRefWhole :: Mutable m a => Ref m a > Ref m a > m ()
 cloneRefWhole :: Mutable m a => Ref m a > m (Ref m a)
 modifyRef :: Mutable m a => Ref m a > (a > a) > m ()
 modifyRef' :: Mutable m a => Ref m a > (a > a) > m ()
 updateRef :: Mutable m a => Ref m a > (a > (a, b)) > m b
 updateRef' :: Mutable m a => Ref m a > (a > (a, b)) > m b
 modifyRefM :: Mutable m a => Ref m a > (a > m a) > m ()
 modifyRefM' :: Mutable m a => Ref m a > (a > m a) > m ()
 updateRefM :: Mutable m a => Ref m a > (a > m (a, b)) > m b
 updateRefM' :: Mutable m a => Ref m a > (a > m (a, b)) > m b
 newtype RefFor m a = RefFor {}
 class DefaultMutable m a r  r > a where
 defaultThawRef :: a > m r
 defaultFreezeRef :: r > m a
 defaultCopyRef :: r > a > m ()
 defaultMoveRef :: r > r > m ()
 defaultCloneRef :: r > m r
 defaultUnsafeThawRef :: a > m r
 defaultUnsafeFreezeRef :: r > m a
 newtype VarMut a = VarMut {
 getVarMut :: a
 newtype CoerceMut s a = CoerceMut {
 getCoerceMut :: s
 newtype TraverseMut f a = TraverseMut {
 getTraverseMut :: f a
 newtype Immutable a = Immutable {
 getImmutable :: a
 reMutable :: forall m n a r. (Mutable m a, Monad n) => (forall x. m x > n x) > (Mutable n a => r) > r
 reMutableConstraint :: forall m n a. (Mutable m a, Monad n) => (forall x. m x > n x) > Mutable m a : Mutable n a
 type family MapRef m as where ...
Documentation
class Monad m => Mutable m a where Source #
An instance of
means that Mutable
m aa
can be stored
a mutable reference in monad m
.
The associated type
links any Ref
m aa
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 twofold:
 Piecewisemutable values, so you can write to only one part and not
others. This also allows for cheaper "writes", even if you replace
the whole value: you don't need to ever synthesize an entire new
value, you can keep each component in a separate variable until you
freezeRef
it out. This can be especially useful for composite data types containing large structures likeVector
. Generic abstractions (similar to
Show
), so you can automatically derive instances while preserving piecewiseness. For example, the instanceinstance (Mutable m a, Mutable m b) => Mutable m (a, b)
If
a
andb
are piecwisemutable, then the instance here will appropriately utilize that fact.
To modify the specific parts of mutable values, it can be useful to use the functions in Data.Mutable.Parts.
There are facilities to automatically piecewise mutable versions for
userdefined instances of Generic
.
For example, if we have a type like:
data TwoVectors = TV { tvInt ::Vector
Int , tvDouble :: Vector Double } deriving Generic instance Mutable m TwoVectors where type Ref m TwoVectors =GRef
m TwoVectors
Then now we get:
thawRef
:: TwoVectors > m (GRef
m TwoVectors)freezeRef
::GRef
m TwoVectors > m TwoVectors
And
is now a piecewisemutable 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
GRef
m TwoVectorsMVector
s. If the two vectors are large, this can be much more
efficient to modify (if you are modifying several times) than by just
doing alterations on TwoVector
s. It is also much better for large
vectors if you plan on modifying only a single item in the vector.
If you are using the "higherkinded" data pattern, a la https://reasonablypolymorphic.com/blog/higherkindeddata/, then we can also do:
data TwoVectors f = TV { tvInt ::HKD
f (Vector
Int) , tvDouble :: HKD f (Vector Double) } deriving Generic instance Mutable (TwoVectorsIdentity
) where type Ref (TwoVectorsIdentity
) = TwoVectors (RefFor
m)
And now your mutable ref is literally going to be a product of the components
ghci> tvr@(TV is ds) < thawRef (TV xs ys) ghci> :t tvr TV (RefFor
IO) ghci> :t isMVector
RealWorld Int ghci> :t dsMVector
RealWorld Double
So thawRef
will actually just get you the same record type but with
the mutable versions of each field. If you modify the mutable fields,
and then later freezeRef
the whole thing, the resulting frozen value
will incorporate all of the changes to the individual fields.
In addition, there are a few more "automatically derived" instances you
can get by picking Ref
:
 Make a mutable version for any newtype wrapper, using the Mutable
 of the underlying type
newtype MyType = MT (Vector Double)
type Ref m MyType = CoerceRef m MyType (Vector Double)
 Make a mutable version of any container, where the items are all
 mutable references.
data MyContainer a = MC a a a a
deriving (Functor, Foldable, Traversable)
type Ref m (MyContainer a) = TraverseRef m MyContainer a
See https://mutable.jle.im/02mutableandref.html for more information on this typeclass and how to define instances automatically, and also
 https://mutable.jle.im/05mutableparts.html for more information on dealing with record types
 https://mutable.jle.im/06mutablebranches for more information on dealing with sum types
Nothing
type Ref m a = (v :: Type)  v > a Source #
Links the type a
to the type of its canonical "mutable version".
For example, for Vector
, the mutable version is MVector
, so
we have
type Ref m (Vector
a) =MVector
(PrimState
m) 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, s ~PrimState
m) =>Vector
a > m (Vector
s a)freezeRef
:: (PrimMonad
m, s ~PrimState
m) =>Vector
s a > m (Vector
a)copyRef
:: (PrimMonad
m, s ~PrimState
m) =>Vector
s a >Vector
a > m ()
This associated type must be unique for a
, so no two types a
can
have the same
. This makes type inference a lot more
useful: if you use Ref
m afreezeRef
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 nonmutable type. You
won't get any of the performance benefits of piecewise mutation from
it, but it is useful as a base case for noncomposite types like
Int
.
There are some builtin alternative options for userdefined ADTs
with Generic
instances:
 Works for allGeneric
instances, preserves piecewise mutation  for products type Ref m a =GRef
m a
If you just set up a blank instance, the implementations of
thawRef
, freezeRef
, and copyRef
will be inferred using
DefaultMutable
.
data MyType  The default setup is OK instance Mutable m MyType  This is equivalent to the above instance Mutable m MyType type Ref m MyType =MutVar
(PrimState
m) MyType  anyGeneric
instance data MyType = MyType { mtInt :: Int, mtDouble :: Double } deriving Generic instance Mutable m MyType where type Ref m MyType =GRef
m MyType
See https://mutable.jle.im/02mutableandref.html for more information on this type family and how to define instances automatically.
thawRef :: a > m (Ref m a) Source #
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, s ~PrimState
m) =>Vector
a > m (Vector
s a)
For noncomposite (like Int
), this is often called the "new var"
function, like newIORef
/ newSTRef
/ newMutVar
etc.
freezeRef :: Ref m a > m a Source #
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, s ~PrimState
m) =>Vector
s a > m (Vector
a)
For noncomposite (like Int
), this is often called the "read var"
function, like readIORef
/ readSTRef
/ readMutVar
etc.
:: Ref m a  destination to overwrite 
> a  value 
> m () 
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, s ~PrimState
m) =>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 noncomposite (like Int
), this is often called the "write var"
function, like writeIORef
/ writeSTRef
/ writeMutVar
etc.
Deep Copymove a mutable reference on top of another, overwriting the second one.
For noncomposite 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.
cloneRef :: Ref m a > m (Ref m a) Source #
Create a deep copy of a mutable reference, allocated to a separate independent reference.
For noncomposite 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.
unsafeThawRef :: a > m (Ref m a) Source #
A noncopying 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.
unsafeFreezeRef :: Ref m a > m a Source #
A noncopying 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.
thawRef :: DefaultMutable m a (Ref m a) => a > m (Ref m a) Source #
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, s ~PrimState
m) =>Vector
a > m (Vector
s a)
For noncomposite (like Int
), this is often called the "new var"
function, like newIORef
/ newSTRef
/ newMutVar
etc.
freezeRef :: DefaultMutable m a (Ref m a) => Ref m a > m a Source #
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, s ~PrimState
m) =>Vector
s a > m (Vector
a)
For noncomposite (like Int
), this is often called the "read var"
function, like readIORef
/ readSTRef
/ readMutVar
etc.
:: DefaultMutable m a (Ref m a)  
=> Ref m a  destination to overwrite 
> a  value 
> m () 
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, s ~PrimState
m) =>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 noncomposite (like Int
), this is often called the "write var"
function, like writeIORef
/ writeSTRef
/ writeMutVar
etc.
:: DefaultMutable m a (Ref m a)  
=> Ref m a  destination 
> Ref m a  source 
> m () 
Deep Copymove a mutable reference on top of another, overwriting the second one.
For noncomposite 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.
cloneRef :: DefaultMutable m a (Ref m a) => Ref m a > m (Ref m a) Source #
Create a deep copy of a mutable reference, allocated to a separate independent reference.
For noncomposite 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.
unsafeThawRef :: DefaultMutable m a (Ref m a) => a > m (Ref m a) Source #
A noncopying 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.
unsafeFreezeRef :: DefaultMutable m a (Ref m a) => Ref m a > m a Source #
Instances
modifyRef :: Mutable m a => Ref m a > (a > a) > m () Source #
Apply a pure function on an immutable value onto a value stored in a mutable reference.
modifyRef' :: Mutable m a => Ref m a > (a > a) > m () Source #
modifyRef
, but forces the result before storing it back in the
reference.
updateRef :: Mutable m a => Ref m a > (a > (a, b)) > m b Source #
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 m a => Ref m a > (a > (a, b)) > m b Source #
updateRef
, but forces the updated value before storing it back in the
reference.
modifyRefM :: Mutable m a => Ref m a > (a > m a) > m () Source #
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 m a => Ref m a > (a > m a) > m () Source #
modifyRefM
, but forces the result before storing it back in the
reference.
updateRefM :: Mutable m a => Ref m a > (a > m (a, b)) > m b Source #
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 m a => Ref m a > (a > m (a, b)) > m b Source #
updateRefM
, but forces the updated value before storing it back in the
reference.
A handy newtype wrapper that allows you to partially apply Ref
.
is the same as RefFor
m a
, but can be partially applied.Ref
m a
If used with HKD
, you can treat this syntactically identically as
a
.Ref
m a
Instances
class DefaultMutable m a r  r > a where Source #
The default implementations of thawRef
, freezeRef
, and copyRef
dispatched for different choices of Ref
.
Basically, by specifying Ref
, you get the rest of the instance for
free.
We have the default case:
 default, if you don't specify Ref
instance Mutable m MyType
 the above is the same as:
instance Mutable m MyType
type Ref m MyType = MutVar (PrimState m) MyType
The case for any instance of Generic
:
instance Mutable m MyType type Ref m MyType = GRef m MyType
The case for the "higherkinded data" pattern a la https://reasonablypolymorphic.com/blog/higherkindeddata/:
instance Mutable m (MyTypeF Identity) type Ref m (MyTypeF Identity) = MyTypeF (RefFor m)
The case for any newtype wrapper:
newtype MyType = MT (Vector Double) instance Mutable m MyType where type Ref m MyType = CoerceRef m MyType (Vector Double)
And the case for any 'Traversable instance, where the items will all be mutable references:
data MyContainer a = MC a a a a deriving (Functor, Foldable, Traversable) instance Mutable m a => Mutable m (MyContainer a) where type Ref m (MyContainer a) = TraverseRef m MyContainer a
defaultThawRef :: a > m r Source #
defaultFreezeRef :: r > m a Source #
defaultCopyRef :: r > a > m () Source #
defaultMoveRef :: r > r > m () Source #
defaultCloneRef :: r > m r Source #
defaultUnsafeThawRef :: a > m r Source #
defaultUnsafeFreezeRef :: r > m a Source #
Instances
Providing and overwriting instances
Newtype wrapper that can provide any type with a Mutable
instance,
giving it a "nonpiecewise" instance. Can be useful for avoiding orphan
instances yet still utilizing autoderiving features, or for overwriting
the Mutable
instance of other instances.
For example, let's say you want to autoderive an instance for your data type:
data MyType = MT Int Double OtherType deriving Generic
This is possible if all of MyType
s 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 autoderived:
instance Mutable m MyType where type Ref m MyType = GRef m MyType
It can also be used to override a Mutable
instance. For example,
even if the Mutable
instance of SomeType
is piecewisemutable, the
Mutable
instance of
will be not be piecewise.VarMut
SomeType
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
to get that
VarMut
String
Mutable
instance.
Instances
PrimMonad m => Mutable m (VarMut a) Source #  
Defined in Data.Mutable.Class thawRef :: VarMut a > m (Ref m (VarMut a)) Source # freezeRef :: Ref m (VarMut a) > m (VarMut a) Source # copyRef :: Ref m (VarMut a) > VarMut a > m () Source # moveRef :: Ref m (VarMut a) > Ref m (VarMut a) > m () Source # cloneRef :: Ref m (VarMut a) > m (Ref m (VarMut a)) Source # unsafeThawRef :: VarMut a > m (Ref m (VarMut a)) Source # unsafeFreezeRef :: Ref m (VarMut a) > m (VarMut a) Source #  
IsoHKD VarMut (a :: Type) Source #  Use a 
type Ref m (VarMut a) Source #  
type HKD VarMut (a :: Type) Source #  
Defined in Data.Mutable.Class 
newtype CoerceMut s a Source #
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 Vector
s Mutable
instance (via
MVector
), but you don't want to write an orphan instance like
instance Mutable m DoubleVec where typeRef
m DoubleVec =CoerceRef
m DoubleVec (Vector Double)
then you can instead use
as the
data type. This wrapped type does use the inderlying CoerceMut
DoubleVec (Vector Double)Mutable
insatnce for Vector
.
CoerceMut  

Instances
IsoHKD (CoerceMut s :: k > Type) (a :: k) Source #  Use a 
(Mutable m a, Coercible s a) => Mutable m (CoerceMut s a) Source #  
Defined in Data.Mutable.Class thawRef :: CoerceMut s a > m (Ref m (CoerceMut s a)) Source # freezeRef :: Ref m (CoerceMut s a) > m (CoerceMut s a) Source # copyRef :: Ref m (CoerceMut s a) > CoerceMut s a > m () Source # moveRef :: Ref m (CoerceMut s a) > Ref m (CoerceMut s a) > m () Source # cloneRef :: Ref m (CoerceMut s a) > m (Ref m (CoerceMut s a)) Source # unsafeThawRef :: CoerceMut s a > m (Ref m (CoerceMut s a)) Source # unsafeFreezeRef :: Ref m (CoerceMut s a) > m (CoerceMut s a) Source #  
type HKD (CoerceMut s :: k > Type) (a :: k) Source #  
Defined in Data.Mutable.Class  
type Ref m (CoerceMut s a) Source #  
Defined in Data.Mutable.Class 
newtype TraverseMut f a Source #
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
is
a normal list of mutable references, instead of a fullon mutable linked
list.Mutable
(TraverseMut
[] a)
TraverseMut  

Instances
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 m MyType where type Ref m MyType = GRef m MyType
This basically uses three mutable references: the Int
, the
, and the Vector
DoubleString
. 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 m MyType where
type Ref m MyType = GRef m MyType
which has that behavior. The Int
and the Vector
will be mutable
within
, but not the Ref
m MyTypeString
.
Immutable  

Instances
Monad m => Mutable m (Immutable a) Source #  
Defined in Data.Mutable.Class thawRef :: Immutable a > m (Ref m (Immutable a)) Source # freezeRef :: Ref m (Immutable a) > m (Immutable a) Source # copyRef :: Ref m (Immutable a) > Immutable a > m () Source # moveRef :: Ref m (Immutable a) > Ref m (Immutable a) > m () Source # cloneRef :: Ref m (Immutable a) > m (Ref m (Immutable a)) Source # unsafeThawRef :: Immutable a > m (Ref m (Immutable a)) Source # unsafeFreezeRef :: Ref m (Immutable a) > m (Immutable a) Source #  
IsoHKD Immutable (a :: Type) Source #  Use an 
type Ref m (Immutable a) Source #  
Defined in Data.Mutable.Class  
type HKD Immutable (a :: Type) Source #  
Defined in Data.Mutable.Class 
Changing underlying monad
reMutable :: forall m n a r. (Mutable m a, Monad n) => (forall x. m x > n x) > (Mutable n a => r) > r Source #
reMutableConstraint :: forall m n a. (Mutable m a, Monad n) => (forall x. m x > n x) > Mutable m a : Mutable n a Source #