packages feed

strict-checked-vars-0.2.1.0: README.md

# Strict `MVar`s and `TVar`s with invariant checking

The `strict-checked-vars` package provides a strict interface to mutable
variables (`MVar`) and `TVar`s with invariant checking. It builds on top of
`strict-mvar`, `strict-stm` and `io-classes`, and thus it provides the interface
for `MVar`/`TVar` implementations for both
[IO](https://hackage.haskell.org/package/base-4.18.0.0/docs/Prelude.html#t:IO)
and [io-sim](https://hackage.haskell.org/package/io-sim).

## Checked and unchecked variants

There are currently two variant implementations of `StrictTVar`s.
* From `strict-stm`: `Control.Concurrent.Class.MonadSTM.Strict.TVar`
* From `strict-checked-vars`: `Control.Concurrent.Class.MonadSTM.Strict.TVar.Checked`

Similarly, there are currently two variant implementations of `StrictMVar`s.
* From `strict-mvar`: `Control.Concurrent.Class.MonadMVar.Strict`
* From `strict-checked-vars`: `Control.Concurrent.Class.MonadMVar.Strict.Checked`


The _unchecked_ modules provide the simplest implementation of strict variables:
a light wrapper around lazy variables that forces values to WHNF before they are
put inside the variable. The _checked_ module does the exact same thing, but it
has the additional feature that the user can provide an invariant that is
checked each time a new value is placed inside the variable. The checked modules
are drop-in replacements for the unchecked modules, though invariants will be
trivially true in that case. Non-trivial invariants can be set when creating a
new variable.

```haskell
newMVarWithInvariant :: MonadMVar m
                     => (a -> Maybe String)
                     -> a
                     -> m (StrictMVar m a)

newEmptyMVarWithInvariant :: MonadMVar m
                          => (a -> Maybe String)
                          -> m (StrictMVar m a)

newTVarWithInvariant :: (MonadSTM m, HasCallStack)
                     => (a -> Maybe String)
                     -> a
                     -> STM m (StrictTVar m a)

newTVarWithInvariantIO :: (MonadSTM m, HasCallStack)
                       => (a -> Maybe String)
                       -> a
                       -> m (StrictTVar m a)
```

**Note:** though the checked modules are drop-in replacements for the unchecked
modules, the `StrictMVar`/`StrictTVar` types are distinct. This means we can't
make mixed use of the checked and unchecked modules.

## Guarantees for invariant checking on `StrictMVar`s

Although all functions that modify a checked `StrictMVar` will check the
invariant, we do *not* guarantee that the value inside the `StrictMVar` always
satisfies the invariant. Instead, we *do* guarantee that if the `StrictMVar` is
updated with a value that does not satisfy the invariant, an exception is thrown
*after* the new value is written to the `StrictMVar`. The reason for this weaker
guarantee is that leaving an `MVar` empty can lead to very hard to debug
"blocked indefinitely" problems.