New functions: dejafuDiscard and dejafuDiscardIO
No dejafusDiscard and dejafusDiscardIO, because I think the
combination of discarding + sharing traces would be very confusing.
Also, the dejafus* functions are for when you want to trade space for
time, whereas the *Discard* functions are for the opposite. So it
doesn't make much sense.
Often checking every seed is unnecessary to compute the result of
checkWithSeeds. The first failure always suffices for weak refinement
and equivalence, and sometimes suffices for strict refinement.
As mapM in IO is strict, composing listToMaybe with counterExamples
necessitates finding ALL counterexamples first, even though only the
first is returned. So an improvement is gained by manually making it
"lazy".
New coverage report, as there have been a bunch of new tests since the
one in the CONTRIBUTING file was generated:
54% expressions used (4311/7948)
51% boolean coverage (67/131)
47% guards (50/106), 31 always True, 6 always False, 19 unevaluated
57% 'if' conditions (11/19), 2 always True, 1 always False, 5 unevaluated
100% qualifiers (6/6)
61% alternatives used (413/671)
83% local declarations used (212/254)
28% top-level declarations used (313/1099)
This lets dejafu test CoCo-style properties, and introduces a
dependency on [leancheck][].
For example, consider this statement about MVars: "using readMVar is
better than a takeMVar followed by a putMVar because the former is
atomic but the latter is not."
This module can test properties like that:
```
sig e = Sig
{ initialise = maybe newEmptyMVar newMVar
, observe = \v _ -> tryReadMVar v
, interfere = \v s -> tryTakeMVar v >>
maybe (pure ()) (void . tryPutMVar v) s
, expr = e
}
> check $ sig (void . readMVar) `equivalentTo`
sig (\v -> takeMVar v >>= putMVar v)
*** Failure: (seed Just ())
left: [(Nothing,Just ())]
right: [(Nothing,Just ()),(Just Deadlock,Just ())]
```
The two expressions are not equivalent, and we get given the
counterexample!
In addition to "equivalentTo", there is also "refines" and
"strictlyRefines" (and negated variants)
[leancheck]: https://hackage.haskell.org/package/leancheck
- `lint.sh` runs HLint, returning 1 if HLint is NOT version 1 (as the
.hlint.yaml configuration file is only supported in version 2 and
later) AND issues are found.
- `style.sh` runs stylish-haskell. I would like it to return 1 if it
reformatted anything, but the tool doesn't appear to support
reporting that :(