Zulip Chat Archive

Stream: new members

Topic: Infer the most general type


Patrick Johnson (Nov 14 2021 at 19:33):

Is there a way to tell Lean to infer the most general type for a definition?

universes u v w
variable {α : Sort u}
variable {β : Sort v}
variable {γ : Sort w}
def K (a : α) (b : β) := a
def S (a : α  β  γ) (b : α  β) (c : α) := a c (b c)
def I := S K K -- error

It works if I write types explicitly: def I : α → α := S K (@K _ Type), but how can I make it implicit?

Eric Wieser (Nov 14 2021 at 19:44):

Are you sure you want Type and not (Type u) or (Type v) or ...

Patrick Johnson (Nov 14 2021 at 19:51):

It doesn't affect the final type of I. The second argument of the last K is ignored.

def I : α  α := S K (@K _ Type)
#check @I -- I : Π {α : Sort u_1}, α → α

Reid Barton (Nov 14 2021 at 19:51):

You can also put any random type like int there, yeah.

Reid Barton (Nov 14 2021 at 19:52):

A priori they could all define different functions I, so you should say which one you mean

Reid Barton (Nov 14 2021 at 19:52):

Haskell has some defaulting rule for situations like this because it can assume that all your definitions are parametric

Reid Barton (Nov 14 2021 at 19:59):

here is maybe a more familiar example:

def z :  := list.length []  -- error: don't know how to synthesize placeholder

Kyle Miller (Nov 14 2021 at 20:06):

For

def I := S (@K α _) (@K _ ) -- works
def I := S K (@K _ ) -- doesn't work

a reason it doesn't work is that Lean doesn't do Hindley-Milner type inference. A key step of the algorithm is abstraction of metavariables at binding sites, but Lean instead says "don't know how to synthesize placeholder" in this situation.

Kyle Miller (Nov 14 2021 at 20:07):

Elaborating on what Reid said about how they could all define different functions I: the types might be the same for the various choices, but the definitions potentially might not be equal. (They are in this case, though.)

Kyle Miller (Nov 14 2021 at 20:15):

I don't use let expressions enough to have noticed that it checks for metavariables:

example : list  :=
let x := []  -- don't know how to synthesize placeholder
in x

This is a place where Hindley-Milner would abstract the metavariable and make x be polymorphic.

The let tactic allows metavariables, though:

example : list  :=
begin
  let x := [],
  exact x
end

Last updated: Dec 20 2023 at 11:08 UTC