# 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.