This is a hard coded extra case. It is not an instance of has_coe.
Even if we change has_coe to accomodate this case, it will not be a
satisfactory solution because this coercion depends on the element and
not the type, and the element usually contains metavariables.
We should eventually write a tactic for synthesizing coercions.
I kept a few core methods (e.g., exact_core and apply_core). Reason:
if we use default parameters
meta constant exact (e : expr) (md := semireducible) : tactic unit
then, we will not be able to write
to_expr p >>= exact
The workaround is
do t <- to_expr p, exact t
or
to_expr p >>= (fun x, exact x)
One alternative is to change how we handle default parameters, and
eta-expand applications that involve default parameters.
We may also have an attribute [eta_expand]. Then
attribute [eta_expand] foo
instructs the elaborator to automatically eta-expand foo-applications.
The attribute would give users more control, and avoid potential
performance problems. Without the attribute, then for every function
application the elaborator has to check the type and decide whether it
must be eta-expanded or not.
@gebner @kha What do you think?
Some inference produce terms with large useless redexes such as
(prod.fst (prod.mk _ _)). Since we do normalization during
preprocessing, we can avoid ever even looking at these terms.
simp interacts badly with super's term ordering. I believe a better
approach is to pick the term ordering according to the available simp
rules, as in "More SPASS with Isabelle".
It produces non-termination because it triggers sub-problems of the
form (has_monad_lift_t t ?M), and this kind of sub-problem is bad
for the transitive closure rule:
instance has_monad_lift_t_trans (m n o) [has_monad_lift n o] [has_monad_lift_t m n] : has_monad_lift_t m o
The trick above only behaves well for synthesis subproblems that do not
contain sub-variables.
Note that the sub-problem (has_monad_lift_t t ?M) is created by a
similar rule used at has_coe_t.
instance {a : Type u₁} {b : Type u₂} {c : Type u₃} [has_coe a b] [has_coe_t b c] : has_coe_t a c
AND
instance {m n} [has_monad_lift_t m n] {α} : has_coe (m α) (n α) :=
We workaround the issue by disabling
instance {m n} [has_monad_lift_t m n] {α} : has_coe (m α) (n α)
and adding instances of it. Example:
meta instance (α : Type) : has_coe (tactic α) (solver α) := ...
meta instance (α : Type) : has_coe (tactic α) (prover α) := ...
meta instance (α : Type) : has_coe (tactic α) (smt_tactic α) := ...
We also removed the notation (♯tac) since it is not needed anymore.
@gebner, the comment at elaborator.cpp explains why you had to use the ♯
notation. The workaround is a little bit hackish, but I think it is
worth it. We will use monad lifts in many different places.