lean4-htt/library/init
Leonardo de Moura 118c909504 feat(frontends/lean/elaborator,library/type_context): fine grain unifier approximation control
Now, the elaborator only uses the quasi-pattern unifier approximation
for inferring the implicit motive in recursor-like applications.

This change was motivated by counterintuitive behavior associated with
this approximation. For example, before this commit

```
variables {δ σ : Type}

def ex1 : state_t δ (state_t σ id) σ :=
monad_lift (get : state_t σ id σ) -- doesn't work

def ex2 : state_t δ (state_t σ id) σ :=
do s ← monad_lift (get : state_t σ id σ), -- works
   return s
```

The first one doesn't work because when we elaborate
`@monad_lift ?m ?n ?c ?α (get : state_t σ id σ) : ?n ?α`
with expected type `state_t δ (state_t σ id) σ`
It first produces the following unification problem by processing
matching the inferred type with the expected one.
```
?n ?α =?= state_t δ (state_t σ id) σ
==> (approximate using first-order unification)
?n := state_t δ (state_t σ id)
?α := σ
```

Then we try to solve
```
?m ?α =?= state_t σ id σ
==> instantiate metavars
?m σ =?= state_t σ id σ
==> (approximate since it is a quasi-pattern unification constraint)
?m := λ σ, state_t σ id σ
```

Remark: the constraint is not a Milner pattern because `σ` is in
the local context of `?m`. By assuming it is a Milner pattern,
we are ignoring the other possible solutions:
```
?m := λ σ', state_t σ id σ
?m := λ σ', state_t σ' id σ
?m := λ σ', state_t σ id σ'
```

We need the quasi-pattern approximation for elaborating recursors.
So, this commit enable this kind of approximation only when
elaborating recursors and executing induction-like tactics.

If we had used first-order unification, then we would have produced
the right answer: `?m := state_t σ id`

Haskell would solve this example since it always uses
first-order unification during elaboration.

The second one works because when we elaborate
`monad_lift (get : state_t σ id σ)`, the expected type is `state_t δ (state_t σ id) ?α`.
So, `?m ?α =?= state_t σ id σ` will not considered to be a quasi-pattern
since `?α` is not yet assigned to a local constant.

We are not fully confident this commit produces a better user
experience. We know that

- Full higher-order unification (used in Lean2) produces a combinatoric
explosion, and generates a lot of non-termination in complex type class
hierarchies (monad library, has_coe, etc). The problem is that
higher-order unification manages to create new solutions that we
cannot find using first-order unification.

- Lean3 is more reliable than Lean2 for elaborating monadic code because
 it does not use higher-order unification.

- For elaborating recursor-like applications, we need at least the
quasi-patterns. We need it when trying to infer the implicit
motive. First-order unification works poorly in this case.  Note that
the lack of higher-order unification in Lean3 forces us to provide the
motive explicitly for terms that Lean2 can elaborate.

- We need quasi-patterns for solving unification constraints in the
induction-like tactics. Similar to the previous item. We use it to infer
the motive. (edited) I will try to disable the quasi-pattern
approximation when elaborating regular applications. At least, we will
behave like Haskell for this kind of application.
2018-04-24 15:09:19 -07:00
..
category feat(library/init/compiler/ir): use run_state and run_reader 2018-04-24 12:48:12 -07:00
compiler chore(library/init/compiler/ir): cleanup 2018-04-24 13:00:39 -07:00
data feat(library/init/data): add uint16 and make sure uint* - uses wraparound semantics like most programming languages 2018-04-20 18:27:13 -07:00
meta chore(library): cleanup constants.txt 2018-04-12 16:43:11 -07:00
classical.lean refactor(init/classical): simplify classical proofs 2017-07-28 16:47:53 +01:00
coe.lean chore(library/init/coe): document why @[reducible] annotation is needed 2018-01-16 11:31:43 -08:00
core.lean feat(frontends/lean/definition_cmds): elaborate a def's type separately when explicit return type is given 2018-04-20 09:59:09 -07:00
default.lean chore(*): remove algebra 2018-04-10 15:53:14 -07:00
function.lean feat(init): some simp lemmas 2018-03-01 16:07:52 +01:00
funext.lean chore(*): disable SMT tactic framework and backward chaining 2018-04-10 12:05:51 -07:00
init.md
ite_simp.lean feat(library/init/ite_simp): add simp lemmas 2017-11-06 12:34:52 -08:00
logic.lean feat(frontends/lean/elaborator,library/type_context): fine grain unifier approximation control 2018-04-24 15:09:19 -07:00
propext.lean feat(frontends/lean): add support for t.<id> and t.<idx> when t is a composite term 2017-03-28 17:47:49 -07:00
util.lean refactor(library): has_to_string ==> has_repr 2017-06-18 18:29:19 -07:00
version.lean.in chore(leanpkg/lean_version): recognize nightlies as releases separate from master 2018-03-20 15:14:45 -07:00
wf.lean feat(frontends/lean/definition_cmds): elaborate a def's type separately when explicit return type is given 2018-04-20 09:59:09 -07:00