Zulip Chat Archive
Stream: lean4
Topic: Implicit variables from context
Zygimantas Straznickas (Mar 01 2022 at 23:13):
Is it possible to get Lean to fill in implicit arguments using matching-type terms in the current context? In Coq I would often do this:
Record PointedType := mkPointedType {
T : Type ;
mkT : T
}.
Inductive PointedTypeVal {P : PointedType} :=
| mk : P.(T) -> PointedTypeVal.
Definition test {P : PointedType} : PointedTypeVal := mk P.(mkT).
(* or *)
Variable (P : PointedType).
Definition test2 : PointedTypeVal := mk P.(mkT).
In Lean it doesn't seem to work:
structure PointedType where
T : Type
mkT : T
inductive PointedTypeVal {P : PointedType} where
| mk : P.T -> PointedTypeVal
set_option pp.all true
def test {A : PointedType} : PointedTypeVal := PointedTypeVal.mk A.mkT
-- error (in the return type specification):
-- @PointedTypeVal : {P : PointedType} → Type
-- don't know how to synthesize implicit argument
-- @PointedTypeVal (@?m.649 A)
-- context:
-- A : PointedType
-- ⊢ PointedType
-- when the resulting type of a declaration is explicitly provided, all holes (e.g., `_`) in the header are resolved before the declaration body is processed
variable {A : PointedType}
def test2 : PointedTypeVal := PointedTypeVal.mk A.mkT
-- same error
Mario Carneiro (Mar 01 2022 at 23:43):
It looks like the behavior has changed from lean 3 here. In general, lean definitely will use unification to fill implicit arguments, and in lean 3, it will do what you are hoping. In lean 4, the type of the declaration is elaborated separately from the body when it is provided, meaning that it will only infer the type if it could also infer the type when the body is sorry
. However you can leave the type off completely, in which case it will use the body to infer the type, so you can write this instead:
-- this works
def test {A : PointedType} := PointedTypeVal.mk A.mkT
-- also this
def test2 {A : PointedType} := (PointedTypeVal.mk A.mkT : PointedTypeVal)
def test3 {A : PointedType} := show PointedTypeVal from PointedTypeVal.mk A.mkT
Mario Carneiro (Mar 01 2022 at 23:45):
@Zygimantas Straznickas
Zygimantas Straznickas (Mar 01 2022 at 23:46):
Thanks, that works!
Zygimantas Straznickas (Mar 01 2022 at 23:59):
Actually, is there a similar workaround I can use when providing argument types? E.g. making def test (v : PointedTypeVal) := v
work?
Mario Carneiro (Mar 02 2022 at 00:01):
def test := fun (v : PointedTypeVal) => v
Mario Carneiro (Mar 02 2022 at 00:02):
not that this will work, because that body won't help to infer the argument anyway
Last updated: Dec 20 2023 at 11:08 UTC