Zulip Chat Archive

Stream: general

Topic: Type inference on `→` vs `≃`


Eric Wieser (Oct 01 2020 at 14:53):

Why is lean able to infer types for the expression using f () but not g ()?

import data.real.basic
import data.equiv.basic

def wrapped (α : Type) := α

variables {α : Type}

def f : α  wrapped α := sorry
def g : α  wrapped α := sorry

variables (n : ) (x : )

#check (f (n * x) : wrapped )   -- ok, lean works out that I mean
#check (f (n * x : ) : wrapped )   -- this, which also works

#check (g (n * x) : wrapped )   -- fail - why can't lean work out that I mean
#check (g (n * x : ) : wrapped )  -- this, which doesn't fail

(this makes #4346 fail)

Adam Topaz (Oct 01 2020 at 15:04):

This works:

#check (g ((n : ) * x) : wrapped )

Adam Topaz (Oct 01 2020 at 15:05):

It must be something about how lean decides to coerce a function

Adam Topaz (Oct 01 2020 at 15:06):

My guess is that it sees n which has type nat and things "okay, g should be a function on nat" and then it doesn't know what to do with the x which is a real number.

Chris Hughes (Oct 01 2020 at 15:06):

For the elaborator has to search for a has_coe_to_fun instance for equiv. It has something to do with that, not sure of the precise details.

Eric Wieser (Oct 01 2020 at 15:07):

Once it finds the docs#has_coe_to_fun instance, shouldn't it discover that g coerces to α → wrapped α, and apply the same rules as f?

Adam Topaz (Oct 01 2020 at 15:07):

But it sees nfirst.

Adam Topaz (Oct 01 2020 at 15:07):

So I imagine it thinks g should be a function on nat.

Eric Wieser (Oct 01 2020 at 15:08):

type inference is outside in, isn't it?

Adam Topaz (Oct 01 2020 at 15:08):

For example both

#check (g x)
#check (g n)

work

Adam Topaz (Oct 01 2020 at 15:09):

Yeah, but I think this means that it would look for a coercion of g to a function from nat to wrapped \R.

Adam Topaz (Oct 01 2020 at 15:09):

But honestly I don't really know the details of how this stuff works. @Mario Carneiro is probably the person to ask.

Eric Wieser (Oct 01 2020 at 15:11):

But that's not how the API of has_coe_to_fun looks - it's not like has_coe where there's a target type too - has_coe_to_fun.F specifies the type once it has been found for g

Adam Topaz (Oct 01 2020 at 15:13):

So the error under the g in your example says: term has type wrapped \N but it is expected to have type wrapped \R. So this makes me think that it sees n, and finds the coercion of gto \a \to wrapped \a, but fails because you explicitly told it to have type wrapped \R.

Adam Topaz (Oct 01 2020 at 15:14):

There is also an error under * because it doesn't know how to handle the coercion from nto \R.

Eric Wieser (Oct 01 2020 at 15:14):

If you look at the order of the errors in the output log, the * error comes first

Adam Topaz (Oct 01 2020 at 15:15):

This works:

#check (g (n * x) : wrapped )

Eric Wieser (Oct 01 2020 at 15:15):

As does reversing the order of the multiply

Adam Topaz (Oct 01 2020 at 15:16):

Also this:

#check (g $ n * x)

Eric Wieser (Oct 01 2020 at 15:18):

Thanks for suggesting , that seems unobtrusive enough to solve my problem. Would still like to hear from @Mario Carneiro why things are the way that they are.


Last updated: Dec 20 2023 at 11:08 UTC