(~) and (!) are parsed inconsistently in types (plus documentation warts)
(Spawned from #10056?replyto=41\##15457)
`~` and `!` are slightly special in the parser to allow strict annotations and lazy annotations (with `-XStrict`) in data types. As a result, we initially parse all uses of `~`/`!` as bangs, and we use a post-parsing pass (`mergeOps`/`splitTilde`) to figure out which uses of `~` are actually meant to refer to the equality type constructor.
There's a couple of unsatisfying things here:
1. `splitTilde` handles `~`, but not `!`. This means that any use of `!` as a type operator will not work, as evidenced by this GHCi session:
```
λ> type a ! b = Either a b
<interactive>:1:6: error:
Malformed head of type or class declaration: a !b
```
> We should update `splitTilde` to handle `!` as well. (And perhaps give that function a new name to reflect its more ambitious goals.)
1. `Note [Parsing ~]` is supposed to explain all of this hullabaloo, but it does a rather poor job of it. Let's add some more prose to it.
<details><summary>Trac metadata</summary>
| Trac field | Value |
| ---------------------- | ----------------- |
| Version | 8.4.3 |
| Type | Bug |
| TypeOfFailure | OtherFailure |
| Priority | normal |
| Resolution | Unresolved |
| Component | Compiler (Parser) |
| Test case | |
| Differential revisions | |
| BlockedBy | |
| Related | |
| Blocking | |
| CC | |
| Operating system | |
| Architecture | |
</details>
<!-- {"blocked_by":[],"summary":"(~) and (!) are parsed inconsistently in types (plus documentation warts)","status":"New","operating_system":"","component":"Compiler (Parser)","related":[],"milestone":"8.8.1","resolution":"Unresolved","owner":{"tag":"Unowned"},"version":"8.4.3","keywords":[],"differentials":[],"test_case":"","architecture":"","cc":[""],"type":"Bug","description":"(Spawned from https://ghc.haskell.org/trac/ghc/ticket/10056?replyto=41#comment:41)\r\n\r\n`~` and `!` are slightly special in the parser to allow strict annotations and lazy annotations (with `-XStrict`) in data types. As a result, we initially parse all uses of `~`/`!` as bangs, and we use a post-parsing pass (`mergeOps`/`splitTilde`) to figure out which uses of `~` are actually meant to refer to the equality type constructor.\r\n\r\nThere's a couple of unsatisfying things here:\r\n\r\n1. `splitTilde` handles `~`, but not `!`. This means that any use of `!` as a type operator will not work, as evidenced by this GHCi session:\r\n\r\n{{{\r\nλ> type a ! b = Either a b\r\n\r\n<interactive>:1:6: error:\r\n Malformed head of type or class declaration: a !b\r\n}}}\r\n\r\n We should update `splitTilde` to handle `!` as well. (And perhaps give that function a new name to reflect its more ambitious goals.)\r\n2. `Note [Parsing ~]` is supposed to explain all of this hullabaloo, but it does a rather poor job of it. Let's add some more prose to it.","type_of_failure":"OtherFailure","blocking":[]} -->
issue