This PR adds doctests allowing us to write tests for the custom type errors. Having this stuff reified in the test suite means we can iterate on the implementations and give much better QA.
* Allow bidirectional typechecking in the plugin
The plugin used to choke on this:
```haskell
flipShouldBe 11 . sum . fst . run . runFoldMapOutput id $ do
output [1]
output $ replicate 2 5
```
because it would fail to unify `Output (t Int)` (the polymorphic
`Traversable` variable in `sum`) with `Output [Int]`.
In this case, there are no given constraints, so the plugin is
attempting to solve a `Member (Output (t Int)) '[Output [Int]]`. We
reuse the codepath for unifying wanted/givens, pretending like the
`Output (t Int)` is a given.[^1]
[^1]: Pretending it's a wanted breaks something else that I don't
remember right now. This code is brittle :(
So now we have a "wanted" `Output [Int]`, and a "given" `Output (t
Int)`. In general, this thing isn't OK to solve. Consider a real
example:
```haskell
foo :: Member (Output (t Int)) r => Sem r ()
foo = output [5]
```
This is a type error, because the polymorphism goes the wrong way. We
have no guarantees that `t` is supposed to be `[]`.
But in our original example, this isn't a problem, because our `t` isn't
actually in given position. It's just an artifact of reusing the code!
`mkWanted` now takes a new parameter for whether or not it's OK to allow
the givens to be polymorphic.
Such a thing necessitates a change though. We never want to unify
a polymorphic *effect* in given position. Doing so will break Haskell's
regular type inference that determines what the effect row should be,
based on the order in which the interpreters are run.
* Ensure wanted constraints are emitted only once.
This is a fix for the "solveSimpleWanteds: too many iterations" problem
that people are running into. In these cases, the plugin is being asked
to solve the same `Member` constraint several times, and generating
a new wanted each time. In doing so, GHC thinks that work was done, so
it will ask the plugin to run again next time. This process diverges,
and produces the error.
Fixes#79