Zulip Chat Archive
Stream: lean4
Topic: Deriving dependent type from inductive type constructor
Carbon (May 17 2024 at 22:59):
Hello! Very new to pure functional programming, and dependent types, so bear with me. I am trying to create a type that depends on the constructor as follows:
inductive ATest : Nat → Type where
| c (a : Nat) : ATest x
deriving Repr
def ATest_1 := (λ x => (ATest.c x : ATest x)) 1
Ideally, I should have to just do:
def ATest_1 := ATest.c 1 -- Type is ATest 1
Can I improve on the definition of ATest, so I can achieve that?
Chris Bailey (May 18 2024 at 00:32):
I'm on my phone, but I think you just have a typo. The constructor should be c (a : Nat) : ATest a
. You might want to turn off autoimplicits at this stage.
Carbon (May 18 2024 at 01:05):
This was intended to make it work, and not a typo. I am trying to match on the value after:
inductive ATestV1 : Nat → Type where
| c (a : Nat) : ATestV1 a -- Use 'a' instead of 'x' won't work, see later
deriving Repr
inductive ATestV2 : Nat → Type where
| c (a : Nat) : ATestV2 x -- This will work
deriving Repr
def ATestV1_1 := (λ x => (ATestV1.c x : ATestV1 x)) 1
def ATestV2_1 := (λ x => (ATestV2.c x : ATestV2 x)) 1
#eval match ATestV1_1 with | .c x => x -- Does not work
#eval match ATestV2_1 with | .c x => x -- This works
Lucas Allen (May 18 2024 at 05:59):
I'm not sure if this helps, but one thing you can do is this,
inductive ATestV3 : Type where
| c : Nat → ATestV3
deriving Repr
def ATestV3_1 := (λ x => (ATestV3.c x : ATestV3)) 1
#eval match ATestV3_1 with | .c x => x
Marcus Rossel (May 18 2024 at 06:22):
To @Chris Bailey 's point, I think you might be shooting yourself in the foot with Lean's "auto implicits" feature. You can turn this off with set_option autoImplicit false
and see what happens:
inductive ATestV2 : Nat → Type where
| c (a : Nat) : ATestV2 x
-- With auto implicits enabled (by default),
-- the definition of `ATestV2.c` contains an implicit argument 'x'
#check ATestV2.c -- ATestV2.c {x : Nat} (a : Nat) : ATestV2 x
set_option autoImplicit false
inductive ATestV2' : Nat → Type where
| c (a : Nat) : ATestV2' x -- unknown identifier 'x'
Marcus Rossel (May 18 2024 at 06:28):
The only reason Lean could figure out the value of the implicit parameter x
in:
def ATestV2_1 := (ATestV2.c 1 : ATestV2 1)
... is because you explicitly provide the type annotation AVTestV2 1
. Without the type annotation, Lean won't know what x
should be:
def ATestV2_1 := ATestV2.c 1 -- error: don't know how to synthesize implicit argument @ATestV2.c ?x 1
Markus Schmaus (May 18 2024 at 07:22):
Your type ATestV2
probably isn't what you want, since the number in the type and the number in the content are completely unrelated. Your type ATestV1
can only contain numbers that are definitionally equal with the number in the type, this is why the match
doesn't accept a generic variable x
, but needs a concrete 1. ATestV3
in the example below might be want you are hoping for. The number in the type and content don't need to be definitionally equal (defeq), but the constructor requires a proof that they are propositionally equal (propeq), by default it uses by rfl
to proof this equality. The only downside is that deriving Repr
doesn't work.
inductive ATestV1 : Nat → Type where
| c (a : Nat) : ATestV1 a
deriving Repr
inductive ATestV2 : Nat → Type where
| c (a : Nat) : ATestV2 x
deriving Repr
inductive ATestV3 : Nat → Type where
| c (a : Nat) (property : a = b := by rfl) : ATestV3 b
deriving Repr -- doesn't work
def ATestV1_1 := ATestV1.c 1 -- works
def ATestV2_1' := ATestV2.c 1 -- can't work, since the type is unknown
def ATestV2_1 : ATestV2 0 := ATestV2.c 1 -- works, but the number of the type and the content can be different
def ATestV3_1 := ATestV3.c 1 -- works
#eval match ATestV1_1 with | .c x => x -- doesn't work
#eval match ATestV1_1 with | .c 1 => 1 -- works
#eval match ATestV2_1 with | .c x => x -- works
#eval match ATestV3_1 with | .c x h => x -- works, `h` contains the proof that `x` is 1
Carbon (May 18 2024 at 21:25):
Thanks Markus, this indeed captures what I was trying to achieve. I also will keep this autoImplicit
option in mind, thanks all for flagging this.
Last updated: May 02 2025 at 03:31 UTC