Commit graph

2031 commits

Author SHA1 Message Date
Leonardo de Moura
c427fb4086 refactor(*): create library/init/lean folder
The new folder will contain the new parser, macro expander and compiler.
This commit also renames the namespace for the old parser `lean3.parser`
2018-04-27 08:02:40 -07:00
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
Leonardo de Moura
70b181d88f fix(library/type_context): unifier failed to solve ?m =?= fun x_1 ... x_n, ?m x_1 ... x_n
Before this commit, the unifier would try to solve the unification consraint

     ?m =?= fun x_1 ... x_n, ?m x_1 ... x_n

by assigning

     ?m := fun x_1 ... x_n, ?m x_1 ... x_n

which fails the occurs check.

This commit skips the assignment by using eta-reduction.
2018-04-16 14:27:20 -07:00
Leonardo de Moura
008b7b2ac2 fix(library/noncomputable): bug at is_noncomputable
In Lean4, the check should be based on the compiler.
That is, a definition should be marked as noncomputable when we cannot
generate code for it.
2018-04-16 14:26:37 -07:00
Leonardo de Moura
d57c2df9c1 test(tests/lean/run/deriv): add benchmark 2018-04-12 16:43:11 -07:00
Leonardo de Moura
1e11611388 chore(library): cleanup constants.txt 2018-04-12 16:43:11 -07:00
Sebastian Ullrich
726a5547de fix(init/core): typed_expr should accept Props
Fixes #1954
2018-04-12 16:14:47 +02:00
Leonardo de Moura
6234c60aae chore(*): disable test suite 2018-04-10 12:56:55 -07:00
Leonardo de Moura
bcaa0b2ad3 refactor(library/typed_expr): do not use macros for implementing typed_expr
Remark: in Lean4, we will not have macro_defs.
2018-04-09 15:16:46 -07:00
Leonardo de Moura
d387103aa2 fix(library/init/core): closes #1951
- Add has_pow type class
- Make `^` notation right associative
2018-03-29 16:25:47 -07:00
Sebastian Ullrich
3fefe94757 refactor(library/init/core,library/init/unit): make unit an abbreviation of punit.{0} 2018-03-27 10:33:04 -07:00
Leonardo de Moura
efa9d7e110 perf(library/type_context): performance issue when proving equation lemmas 2018-03-26 12:57:19 -07:00
Sebastian Ullrich
7daf6a2133 refactor(init/category): change _functor classes into new _adapter classes, add docs 2018-03-20 14:58:37 -07:00
Sebastian Ullrich
70167def6f refactor(init/category/state): replace monad_state_lift with Haskell's MonadState
* does not leak information about the inner monad via out_param
* can be derived from an inner `monad_state` instance
2018-03-20 14:58:37 -07:00
Sebastian Ullrich
3adc5113cb feat(init/category/state): make zoom work linearly 2018-03-20 14:58:36 -07:00
Sebastian Ullrich
da5c8e21df chore(init/category/cont): move to test 2018-03-20 14:58:36 -07:00
Sebastian Ullrich
e6f5ce1303 doc(init/category/reader): add docs and test 2018-03-20 14:58:36 -07:00
Sebastian Ullrich
e044030cd2 doc(init/category/cont): add docs and test 2018-03-20 14:58:36 -07:00
Sebastian Ullrich
c104d5d34b doc(init/category/state): add docs and tests 2018-03-20 14:58:36 -07:00
Sebastian Ullrich
b372dd94d3 feat(init/category/transformers): add monad_run class 2018-03-20 14:58:36 -07:00
Sebastian Ullrich
69cfdbd290 refactor(init/category): make all monad transformers structures, replace monad classes with has_monad_lift_t wrappers 2018-03-20 14:58:36 -07:00
Sebastian Ullrich
c36393066e feat(init/category): introduce monad_functor and implement it for reader, state, and except 2018-03-20 14:58:36 -07:00
Sebastian Ullrich
788e8695eb refactor(init/category/state): replace modify/put (returning unit) with modify'/put' (returning punit) 2018-03-20 14:58:35 -07:00
Sebastian Ullrich
159b45c74f refactor(init/category/state): introduce monad_state
* rename `read/write` to `get/put`, as in Haskell
* define `state` as `state_t id`
2018-03-20 14:58:35 -07:00
Sebastian Ullrich
1c6861528b refactor(init/category): move monad laws into separate type classes defined after the tactic framework 2018-03-20 14:58:35 -07:00
Sebastian Ullrich
63382cf7e3 chore(init/category/transformers): move monad_transformer, monad_lift out of monad namespace, make universe polymorphic 2018-03-20 14:58:35 -07:00
Leonardo de Moura
169cd87dbe feat(library/system/io): add io.run_tactic
@nunoplopes @aqjune
I had to add a new primitive to allow you to execute a tactic from the
`main` function. The `main` function is in the `io` monad. The new
primitive has type:
```
meta constant io.run_tactic {α : Type} (a : tactic α) : io α
```
I also added a new test that shows how to use it.
The test displays all declarations that have the `nat` prefix.

cc @kha
2018-03-07 12:15:26 -08:00
Leonardo de Moura
832d2358f1 test(tests/lean/run/1942): closes #1942
It seems the assertion violation has been fixed by recent changes.
2018-03-06 17:43:08 -08:00
Leonardo de Moura
2889482fe9 fix(library/init/meta/interactive): fixes #1943 2018-03-06 17:36:18 -08:00
Sebastian Ullrich
cf8dd9e75e feat(fronteds/lean/builtin_exprs): do notation: use overloadable bind instead of has_bind.bind 2018-02-28 12:49:22 +01:00
Sebastian Ullrich
5279f92dae fix(library/tactic/simp_lemmas): avoid rewrite failure with more robust code
The old code assumed `emetas` to be descendingly ordered by tmp idx, which is
not true for rfl lemmas.
2018-02-27 10:59:51 -08:00
Leonardo de Moura
421f2c2ae2 fix(library/tactic/subst_tactic): subst was creating type incorrect motive when using dependent elimination
This commit fix a bug reported at comment
https://github.com/leanprover/lean/issues/1827#issuecomment-368258713

Remark: the original problem reported at issue #1827 has nothing to do
with this bug.
2018-02-26 14:02:10 -08:00
Leonardo de Moura
21812768b0 fix(library/init/meta/interactive): fixes #1889 2018-02-23 12:39:11 -08:00
Leonardo de Moura
46ed0ad677 refactor(library/congr_lemma): remove mk_rel_iff_congr_lemma and mk_rel_eq_congr_lemma 2018-02-21 15:04:20 -08:00
Leonardo de Moura
e023b1001a fix(library/system/random): bug at rand_nat 2018-02-16 11:20:43 -08:00
Leonardo de Moura
1c9648a12d chore(library): remove dead constants 2018-02-15 16:17:43 -08:00
Leonardo de Moura
ac13f8b0f9 feat(library/system/io): add random number generator support in the io monad
@aqjune @nunoplopes: See new tests at tests/lean/run/random.lean

We have two actions in `io`. By default, `io` uses the C++
random number generator, but we can force it to use a `std_gen` with
the action `set_rand_gen`.

def rand (lo : nat := std_range.1) (hi : nat := std_range.2) : io nat
def set_rand_gen : std_gen → io unit
2018-02-15 16:12:08 -08:00
Leonardo de Moura
f786d21b0f feat(library/system): basic support for random numbers
@aqjune @nunoplopes: This commit adds basic support for random numbers.
It defines a random number generator interface, and an basic
implementation based on the Haskell one.
We can add more implementations in the future if neeeded.
The new test program has a few examples.

BTW, this is a pure Lean implementation.
If we need more performance we can provide an implementation
using C++.
2018-02-15 14:36:28 -08:00
Leonardo de Moura
96e02613fc fix(library/compiler/simp_inductive): erase trivial structure bug 2018-02-11 11:43:05 -08:00
Sebastian Ullrich
3f497b8d8e fix(library/constructions/projection): out_params should always be implicit in projections 2018-02-02 08:58:52 -08:00
Sebastian Ullrich
009cff6f79 feat(frontends/lean/elaborator): prefer taking subobjects from structure notation sources as a whole
This guarantees definitional equality on the field as witnessed by the test
2018-02-02 08:58:52 -08:00
Leonardo de Moura
e6a98ffe9c feat(library/type_context): improve unifier first-order approximation
@kha We can now solve unification constraints of the form

         ?m unit =?= itactic

I'm not very confident this new extension will improve usuability
instead of creating new counter-intuitive behavior.
At least, in the process of implementing it, I fixed two bugs,
and removed a nasty hack that was being used in the unifier.
Thus, even if we disable this feature in the future, some good came out
of it.

Although, the new extension locally increases the number of constraints
that can be solved, it may prevent terms that could be elaborated before
from being elaborated. I am not too concerned at this point because
I could not construct a natural example. I encountered one case, but it
was due to a problem that I fixed in the previous commit.
I reconstruct it here for the record. Suppose we have a constraint

         ?m_1 ?m_2 =?= itactic

Without the fix from the previous commit, `itactic` would unfold too
`id_rhs Type (tactic unit)`, and the constrain would be solved as

         ?m_1 := (id_rhs Type)
         ?m_2 := (tactic unit)

It succeeds locally, but the elaboration fails later when it tries to
synthesize the type class `has_bind (id_rhs Type)`.
The previous fixes the problem by making sure `itactic` is unfolded to
`tactic unit` as expected. `id_rhs` is an auxiliary definition
used to implement smart unfolding. That being said, the user could in
principle define `itactic` as `@id Type (tactic unit)`, and the constraint

         ?m_1 ?m_2 =?= itactic

will be solved as

         ?m_1 := (@id Type)
         ?m_2 := (tactic unit)

which is not the solution we want.
2018-01-30 15:42:17 -08:00
Leonardo de Moura
815327fc93 fix(library/equations_compiler): bug at pull_nested_rec
closes #1917
2018-01-30 13:49:47 -08:00
Leonardo de Moura
28b8020995 fix(library/type_context): bug in the unifier
One of the approximations used was generating type incorrect terms.
2018-01-30 12:48:48 -08:00
Leonardo de Moura
39f1cc0bab test(tests/lean/run): add new tests exposing bug in the unifier
This commit also documents the problem at type_context.cpp, and
describes a potential solution.
2018-01-30 12:48:48 -08:00
Gabriel Ebner
aac833c8d4 test(tests/lean/run): test for mk_inj_eq 2018-01-28 09:10:26 -08:00
Leonardo de Moura
77ae133baa fix(library/type_context): preprocess_class
@kha This commit fixes the bug we discussed on slack.
I had to repair one of the tests. The broken test made me
realize that if we use the unbundled approach to define something like
`is_semiring`

```
class is_semiring (α : Type) (plus : α → α → α) (mul : α → α → α) (zero : out_param α) (one : out_param α) :=
...
```
Then, to retrieve a `is_semiring` instance, we need to know `α`, `plus`
and `mul`. This is problematic because we may be in a context where one
of them cannot be inferred. This would force user to manually provide
the missing (input) parameter. We are not considering the unbundled
approach for complex algebraic structures such as `semiring`, `ring` and
`field`, but I wanted to document this limitation here since we may face
it in other type classes.

I think it is a bad idea to add back `inout_param` and have both:
`inout_param` and `out_param`. The previous `inout_param` created
many instabilities and hard to diagnose failures.
2018-01-24 17:30:04 -08:00
Leonardo de Moura
d4e1a4a50a chore(library/system/io): tactic.run_io ==> tactic.unsafe_run_io 2018-01-24 10:32:32 -08:00
Leonardo de Moura
0d83a74b26 fix(library/io,tests/lean): io monad command line arguments, and tests 2018-01-23 15:24:41 -08:00
Leonardo de Moura
0ad5497462 refactor(library/io): make io easier to extend and use 2018-01-23 15:03:31 -08:00