# Getting Started

If you have a data type like:

```
import qualified Data.Vector as V
import qualified Data.Vector.Mutable as MV
data MyType = MT
{ mtInt :: Int
, mtDouble :: Double
, mtVec :: V.Vector Double
}
deriving (Show, Generic)
```

Then you can give it an automatically derived mutable version:

```
instance Mutable s MyType where
type Ref s MyType = GRef s MyType
```

`Ref s MyType`

is now a "mutable `MyType`

", like how `MVector s a`

is a
"mutable `Vector a`

".

We now have some nice operations:

## Whole-wise operations

Sometimes you just want to operate on the whole `MyType`

. Well, you now have:

```
-- | Allocate a mutable 'MyType' in 'ST'
thawRef
:: MyType
-> ST s (Ref s MyType)
-- | "Freeze" a mutable 'MyType'
freezeRef
:: Ref s MyType
-> ST s MyType
-- | Overwrite a mutable 'MyType' with the contents of a pure one.
copyRef
:: Ref s MyType
-> MyType
-> ST s ()
-- | Run an updating function on a whole 'MyType'
modifyRef
:: Ref s MyType
-> (MyType -> MyType)
-> ST s ()
```

These actions are the types specialized `ST`

, the mutable memory monad that
comes with GHC. In truth, the types of these are more polymorphic and are
generalized to work for all mutable monads with `PrimMonad`

instance. The
fully general types are:

```
-- | Allocate a mutable 'MyType' in the monad m
thawRef
:: (PrimMonad m, PrimState m ~ s)
=> MyType
-> m (Ref s MyType)
-- | "Freeze" a mutable 'MyType'
freezeRef
:: (PrimMonad m, PrimState m ~ s)
=> Ref s MyType
-> m MyType
-- | Overwrite a mutable 'MyType' with the contents of a pure one.
copyRef
:: (PrimMonad m, PrimState m ~ s)
=> Ref s MyType
-> MyType
-> m ()
-- | Run an updating function on a whole 'MyType'
modifyRef
:: (PrimMonad m, PrimState m ~ s)
=> Ref s MyType
-> (MyType -> MyType)
-> m ()
```

## Piecewise Operations

This is nice, but we really the juicy stuff: a way to modify each part
individually. For that, we have two main mechanisms: the field name based
ones (using `-XOverloadedLabels`

), and the position based ones (using
`-XTypeApplications`

). We have the continuation-based combinators:

```
-- | Do something with the 'Int' field
withField #mtInt
:: (PrimMonad m, PrimState m ~ s)
=> Ref s MyType
-> (MutVar s Int -> m r)
-> m r
-- | Do something with the 'Vector' field
withField #mtVec
:: (PrimMonad m, PrimState m ~ s)
=> Ref s MyType
-> (MVector s Double -> m r)
-> m r
-- | Do something with the second field, the Double
withPos @2
:: (PrimMonad m, PrimState m ~ s)
=> Ref s MyType
-> (MutVar s Double -> m r)
-> m r
-- | Do something with a tuple of each ref in the type
withTuple
:: (PrimMonad m, PrimState m ~ s)
=> Ref s MyType
-> ((MutVar s Int, MutVar s Double, MVector s Double) -> m r)
-> m r
```

And the `MutPart`

-based ones, which yield a `MutPart s b a`

(a way to "zoom
into" a mutable `a`

, if you have a mutable `b`

), which can be used with
functions like `modifyPart`

and `freezePart`

:

```
-- | Data type to "focus in" on the 'mtDouble' field in a 'MyType'
fieldMut #mtDouble
:: MutPart s MyType Double
-- | Modify the 'Double' in the mutable 'MyType'
modifyPart (fieldMut #mtDouble)
:: Ref s MyType
-> (Double -> Double)
-> m ()
```

```
-- | Data type to "focus in" on the first item in a 'MyType'
posMut @1
:: MutPart s MyType Int
-- | Read out the 'Int' in the mutable 'MyType'
freezePart (posMut @1)
:: Ref s MyPart
-> s Int
```

## Sum Types

We can get `GRef`

for sum types too. As shown earlier, we get a mutable linked
list type for free, and a nice "pop" function if we utilize `constrMB`

:

```
data List a = Nil | Cons a (List a)
deriving (Show, Generic)
infixr 5 `Cons`
instance Mutable s a => Mutable s (List a) where
type Ref s (List a) = GRef s (List a)
consBranch
:: Mutable s a
=> MutBranch s (List a) (a, List a)
consBranch = constrMB #_Cons
popStack
:: (Mutable s a, PrimMonad m, PrimState m ~ s)
=> Ref s (List a)
-> m (Maybe a)
popStack xs = do
c <- projectBranch consBranch xs
forM c $ \(y, ys) -> do
o <- freezeRef y
moveRef xs ys
pure o
```

Read on for more information on how the library
works, or jump right into the library with **Haddock Documentation**!