นี่คือหนึ่งเป็นไปได้มากครับซึ่งเป็นความพยายามที่การยึดตามตัวอักษรแบบนั้ตีความแบบนั้นของย่อหน้านี้:
เมื่อพิสูจน์ว่าเป็นคำให้การ E:N→U
เรื่องทั้งเป็นธรรมชาติของตัวเลขมัน suffices เพื่อพิสูจน์มัน 0
และสำหรับ succ(n)
สันนิษฐานได้เลยว่ามันถือให้ n
,i.e. เราสร้าง ez:E(0)
แล้ว es:∏(n:N)E(n)→E(succ(n))
.
จาก ที่ HoTT หนังสือ(ส่วน 5.1).
นี่คือแผนของสิ่งที่ถูกติดตั้งเพื่อใช้งานในการหัสด้านล่างนี้:
หาสูตรในสิ่งที่มันหมายความว่าจะมีหลักฐานสำหรับรายงานว่า"บาทรัพย์สิน P
ถือสำหรับทุกธรรมชาติเล". ด้านล่างเราจะใช้
trait Forall[N, P[n <: N]]:
inline def apply[n <: N]: P[n]
อยู่ที่ไหนลายเซ็นต์ของ apply
-วิธีการพื้นฐานแล้วบอกว่า"สำหรับทุก n <: N
เราสามารถสร้างหลักฐานของ P[n]
".
โปรดจำไว้ว่าวิธีการเป็นประกาศให้เป็น inline
. นี่คือหนึ่งทางเป็นไปได้เพื่อทำให้แน่ใจว่าหลักฐานที่ ∀n.P(n)
คือซักอย่างซิและสามารถสั่งประมวลผลได้ที่ runtime (อย่างไรก็ตามเห็นแก้ไขประวัติศาสตร์สำหรับทางเลือก proposals กับด้วยตัวคุณเองก่อสร้างพยานเงื่อนไข).
Postulate บางอย่าง induction กฏของธรรมชาติสำหรับตัวเลข ด้านล่างเราจะใช้ตาม formulation:
If
P(0) holds, and
whenever P(i) holds, then also P(i + 1) holds,
then
For all `n`, P(n) holds
ฉันอยากจะเชื่อเลยว่ามันน่าจะเป็นไปได้ที่จะ derive
ช่าง induction หลักการใช้บางอย่า metaprogramming สิ่งอำนวยความสะดว.
เขียนลักฐานสำหรับที่ฐานคดีและ induction คดีของ induction ตามหลักการ
???
ผลประโยชน์
รหัสงั้นดูเหมือนนี้:
sealed trait Nat
class O extends Nat
class S[N <: Nat] extends Nat
type plus[a <: Nat, b <: Nat] <: Nat = a match
case O => b
case S[n] => S[n plus b]
trait Forall[N, P[n <: N]]:
inline def apply[n <: N]: P[n]
trait NatInductionPrinciple[P[n <: Nat]] extends Forall[Nat, P]:
def base: P[O]
def step: [i <: Nat] => (P[i] => P[S[i]])
inline def apply[n <: Nat]: P[n] =
(inline compiletime.erasedValue[n] match
case _: O => base
case _: S[pred] => step(apply[pred])
).asInstanceOf[P[n]]
given liftCoUpperbounded[U, A <: U, B <: U, S[_ <: U]](using ev: A =:= B):
(S[A] =:= S[B]) = ev.liftCo[[X] =>> Any].asInstanceOf[S[A] =:= S[B]]
type NatPlusZeroEqualsNat[n <: Nat] = (n plus O) =:= n
def trivialLemma[i <: Nat]: ((S[i] plus O) =:= S[i plus O]) =
summon[(S[i] plus O) =:= S[i plus O]]
object Proof extends NatInductionPrinciple[NatPlusZeroEqualsNat]:
val base = summon[(O plus O) =:= O]
val step: ([i <: Nat] => NatPlusZeroEqualsNat[i] => NatPlusZeroEqualsNat[S[i]]) =
[i <: Nat] => (p: NatPlusZeroEqualsNat[i]) =>
given previousStep: ((i plus O) =:= i) = p
given liftPreviousStep: (S[i plus O] =:= S[i]) =
liftCoUpperbounded[Nat, i plus O, i, S]
given definitionalEquality: ((S[i] plus O) =:= S[i plus O]) =
trivialLemma[i]
definitionalEquality.andThen(liftPreviousStep)
def demoNat(): Unit = {
println("Running demoNat...")
type two = S[S[O]]
val ev = Proof[two]
val twoInstance: two = new S[S[O]]
println(ev(twoInstance) == twoInstance)
}
มัน compiles,วิ่งและรอยนิ้วมือ:
true
หมายความว่าเราต้องเรียบร้อยแล้ invoked ที่ recursively กำหนดไว้
วิธีการที่สามารถประมวลผลหลักฐานครบกำหนดคลอดแล้วขอประเภท two plus O =:= two
.
ต่อความคิดเห็น
- คน
trivialLemma
เป็นจำเป็นต้องดังนั้น summon
s ในอีก given
คงไม่บังเอิญสร้าง recursive บางอย่างซึ่งเป็นหน่อยน่ารำคาญ
- ที่แยกออก
liftCo
-สำหรับวิธีการ S[_ <: U]
ถูกต้องการเพราะ =:=.liftCo
ไม่อนุญาตให้ประเภท constructors กับด้านบน-ค bounded ประเภทพารามิเตอร์
compiletime.erasedValue
+ inline match
คือสุดยอดไปเลย! มันโดยอัตโนมัติสร้าบางอย่าง runtime-gizmos ที่อนุญาตให้พวกเราต้องทำรูปแบบที่เข้าคู่กับการ"ลบ"ประเภทนี้ได้นะ ก่อนที่ฉันเจอนี่ออกไปฉันพยายามจะสร้างเหมาะสมเป็นพยานเงื่อนไขด้วยตนเอง,แต่นี่ก็ไม่ได้ดูเหมือจำเป็นที่ทั้งหมดมันเป็นเตรียมไว้ให้สำหรับฟรี(ดูแก้ไขประวัติศาสตร์สำหรับเข้าถึงกับตูด้วยตนเองเป็นพยานเงื่อนไข).