test(elabissues): document some of the known problems

This commit is contained in:
Leonardo de Moura 2019-09-21 10:17:26 -07:00
parent 097a127c69
commit 1ecb234a9f
3 changed files with 110 additions and 0 deletions

View file

@ -0,0 +1,48 @@
def f : List Int → Bool := fun _ => true
def ex1 : Bool :=
f [1, 2, 3] -- Works
def ex2 : Bool :=
let xs := [1, 2, 3];
/- The following application fails.
In the Lean3 elaborator, the `;` after `have` and `let` expressions is a "check-point".
The elaborator will resolve type class instances and force pending numeral types to `Nat` if they
have not been assigned yet.
So, `xs` will have type `List Nat`.
Solution: remove "check-point" from `let`, but keep the one on `have`. We use `have` expressions
when proving, and it is nice to make sure the proposition does not have meta-variables before continuing. -/
f xs
def ex3 : IO Bool :=
do
xs ← pure [1, 2, 3];
pure $ f xs -- Works
def ex4 :=
[1, 2, 3].map $ fun x => x+1
def ex5 (xs : List String) :=
/- `r.push x` fails because we don't know the type of `r`.
Potential solution: the elaborator should suspend the elaboration of `fun r x => r.push x`,
elaborate `Array.empty`, and then resume the suspension.
-/
xs.foldl (fun r x => r.push x) Array.empty
inductive Expr
| val : Nat → Expr
| app : Expr → Expr → Expr
instance : HasCoe Nat Expr := ⟨Expr.val⟩
def foo : Expr → Expr := fun e => e
def ex6 :=
/- `1` is elaborated to `HasOne.one ?A ?S : ?A`.
Typing constraints unify `?A =?= Expr`, and
we fail to synthesize `HasOne Expr`.
Users get confused since they have defined `HasCoe Nat Expr`.
Solution: elaborate `1` into `Expr.lit (Literal.natVal 1) : Nat`,
and rely on coercions.
-/
foo 1

View file

@ -0,0 +1,39 @@
inductive Syntax
| atom : String → Syntax
| node : String → Array Syntax → Syntax
instance coe1 : HasCoe String Syntax := ⟨Syntax.atom⟩
instance coe2 {α} : HasCoe (List α) (Array α) := ⟨List.toArray⟩
def ex7 : Syntax :=
/-
We try to elaborate `["bla"]` with expected type `Array Syntax`.
The expected type is "discarded" since we fail to unify `Array Syntax =?= List ?A`
where `List ?A` is the resulting type for `List.cons` application before we process its children.
Remark: the elaborator does **not** try to use coercions here. Even if it tried, it would fail since
`List ?A` contains a meta-variable.
Then, we elaborate `["bla"]` without an expected type and produce a term of type `List String`.
Finally, we fail with a type mismatch between `List String` and `Array Nat`.
We can make it work by using:
```
instance coe3 {α β} [HasCoe α β] : HasCoe (List α) (Array β) := ⟨fun xs => (xs.map (fun x => (coe x : β))).toArray⟩
```
-/
Syntax.node "foo" ["bla"]
def ex8 : Syntax :=
Syntax.node "foo" (List.toArray ["boo"]) -- Works
def ex9 : Syntax :=
/-
We need the type of `["boo"]` to be able to apply `.toArray`.
So, we elaborate `["boo"]` first without expected type, and then
obtain `Array String`, and then a type mismatch between
`Array String` and `Array Syntax`.
We can make it work by using:
```
instance coe3 {α β} [HasCoe α β] : HasCoe (Array α) (Array β) := ⟨fun xs => (xs.map (fun x => (coe x : β)))⟩
```
But, the behavior is still confusing to users.
-/
Syntax.node "foo" ["boo"].toArray

View file

@ -0,0 +1,23 @@
inductive Syntax
| atom : String → Syntax
| node : String → Array Syntax → Syntax
instance coe1 : HasCoe String Syntax := ⟨Syntax.atom⟩
instance coe2 {α} : HasCoe (List α) (Array α) := ⟨List.toArray⟩
def ex10 (s : Syntax) : Syntax :=
Syntax.node "foo" (List.toArray ["boo", s]) -- Works
def ex11 (s : Syntax) :=
[s, "foo"] -- Works
def ex12 (s : Syntax) :=
/-
We don't know the expected type. Before elaborating the `List.cons` applications we know
that the resulting type is `List ?A`. Then, we elaborate `"foo"`, and set `?A := String`.
Then, we fail when we try to elaborate `s` since there is not coercion from `Syntax` to `String`.
Potential solution: add special support for polymorphic nested applications such as `List.cons`, `HasAdd.add`, etc.
Disclaimer: not sure whether we will create even more problems since all nested arguments would have to
be elaborated without an expected type. Perhaps, combined with the "suspension" mechanism it will work great.
-/
["foo", s]