@Kha I had a few issues similar to the `Append` issues.
We used a similar idiom for writing builtin parsers where we may write
```
def p : Parser := "foo " >> "bla "
```
as a shorthand for
```
def p : Parser := symbol "foo " >> symbol "bla "
```
I want to support `builtin syntax` one day :)
That being said, we should decide whether we keep `HAppend`, `HOrElse`,
and `HAndThen` or not.
The only one I wish I had in the past is `HAndThen`.
@Kha This one required a bunch of manual fixes. The main issue is that
before we added the string interpolation feature, we created
`MessageData`s using `++` and coercions. For example, given
`(e : Expr)`, we would write
```
let msg : MessageData := "type: " ++ e
```
and rely on the coercions `String -> MessageData` and
`Expr -> MessageData`, and the instance `Append MessageData`.
However, heterogeneous operators "block" the expected type propagation downwards.
This kind of code is obsolete now since we can write a more compact
version using string interpolation
```
let msg := m!"type: {e}"
```
@Kha The new `rational.lean` test shows their usefulness. We just
define the monorphic version and a coercion, and get a bunch of `HAdd`
instances for free.
Users may add the expensive instances if they want.
The goal is to make sure the default configuration is solid, and
covers all examples we really want to support.
cc @kha @dselsam
The main issue is nontermination for problems that do not have
solution. When using dependent coercions, we keep creating goals of
the form `CoeSort ... (coe (coe (coe ...))) ...`. Same for `CoeFun`.
I am considering simplifying it even further, and making sure
`CoeDep` can be used at most once in a sequence of coercions `CoeTC`.
Another option is to use a very small amount of fuel to
guarantee termination when solving coercion TC problems.
cc @Kha @dselsam