We attempt to decide identity for natural numbers.


In [1]:
import $ivy.`io.github.siddhartha-gadgil::provingground-core-jvm:0.1.1-SNAPSHOT`


Out[1]:
import $ivy.$                                                                   

In [2]:
import provingground._, induction._, scalahott._
import NatRing._


Out[2]:
import provingground._, induction._, scalahott._

import NatRing._

In [3]:
val n = "n" :: NatTyp
val m = "m" :: NatTyp
val k = "k" :: NatTyp


Out[3]:
n: RepTerm[spire.math.SafeLong] = RepSymbObj(Name("n"), Nat.Typ)
m: RepTerm[spire.math.SafeLong] = RepSymbObj(Name("m"), Nat.Typ)
k: RepTerm[spire.math.SafeLong] = RepSymbObj(Name("k"), Nat.Typ)

In [4]:
import spire.implicits._


Out[4]:
import spire.implicits._

In [5]:
import HoTT._
val recNatType = rec(Type)


Out[5]:
import HoTT._

recNatType: Func[Typ[Term], Func[Func[Nat, Func[Typ[Term], Typ[Term]]], Func[Nat, Typ[Term]]]] = LambdaFixed(
  SymbTyp($i, 0),
  LambdaFixed(
    SymbolicFunc($j, Nat.Typ, FuncTyp(Universe(0), Universe(0))),
    Rec(
      SymbTyp($i, 0),
      SymbolicFunc($j, Nat.Typ, FuncTyp(Universe(0), Universe(0)))
    )
  )
)

In [6]:
repl.pprinter.bind(translation.FansiShow.fansiPrint)

In [7]:
recNatType.typ


Out[7]:
res6: Typ[Func[Typ[Term], Func[Func[Nat, Func[Typ[Term], Typ[Term]]], Func[Nat, Typ[Term]]]]] = (𝒰  → ((Nat.Typ → (𝒰  → 𝒰 )) → (Nat.Typ → 𝒰 )))

In [8]:
val recNatNatType = rec(NatTyp ->: Type)


Out[8]:
recNatNatType: Func[Func[RepTerm[spire.math.SafeLong], Typ[Term]], Func[Func[Nat, Func[Func[RepTerm[spire.math.SafeLong], Typ[Term]], Func[RepTerm[spire.math.SafeLong], Typ[Term]]]], Func[Nat, Func[RepTerm[spire.math.SafeLong], Typ[Term]]]]] = ($ag : (Nat.Typ → 𝒰 )) ↦ ($ah : (Nat.Typ → ((Nat.Typ → 𝒰 ) → (Nat.Typ → 𝒰 )))) ↦ rec_{ Nat.Typ ; (Nat.Typ → 𝒰 ) }($ag)($ah)

In [9]:
recNatNatType.typ


Out[9]:
res8: Typ[Func[Func[RepTerm[spire.math.SafeLong], Typ[Term]], Func[Func[Nat, Func[Func[RepTerm[spire.math.SafeLong], Typ[Term]], Func[RepTerm[spire.math.SafeLong], Typ[Term]]]], Func[Nat, Func[RepTerm[spire.math.SafeLong], Typ[Term]]]]]] = ((Nat.Typ → 𝒰 ) → ((Nat.Typ → ((Nat.Typ → 𝒰 ) → (Nat.Typ → 𝒰 ))) → (Nat.Typ → (Nat.Typ → 𝒰 ))))

In [10]:
val A = Type.sym
recNatType(One).typ


Out[10]:
A: Typ[Term] = A
res9_1: Typ[Func[Func[Nat, Func[Typ[Term], Typ[Term]]], Func[Nat, Typ[Term]]]] = ((Nat.Typ → (𝒰  → 𝒰 )) → (Nat.Typ → 𝒰 ))

In [11]:
val step01 = n :-> (A :-> (Zero: Typ[Term]))


Out[11]:
step01: Func[RepTerm[spire.math.SafeLong], Func[Typ[Term], Typ[Term]]] = (_ : Nat.Typ) ↦ (_ : 𝒰 ) ↦ Zero

In [12]:
step01.typ


Out[12]:
res11: Typ[Func[RepTerm[spire.math.SafeLong], Func[Typ[Term], Typ[Term]]]] = (Nat.Typ → (𝒰  → 𝒰 ))

In [13]:
val base0 = recNatType(One)(step01)


Out[13]:
base0: Func[Nat, Typ[Term]] = rec_{ Nat.Typ ; 𝒰  }(Unit)((_ : Nat.Typ) ↦ (_ : 𝒰 ) ↦ Zero)

In [14]:
recNatNatType(base0).typ


Out[14]:
res13: Typ[Func[Func[Nat, Func[Func[RepTerm[spire.math.SafeLong], Typ[Term]], Func[RepTerm[spire.math.SafeLong], Typ[Term]]]], Func[Nat, Func[RepTerm[spire.math.SafeLong], Typ[Term]]]]] = ((Nat.Typ → ((Nat.Typ → 𝒰 ) → (Nat.Typ → 𝒰 ))) → (Nat.Typ → (Nat.Typ → 𝒰 )))

In [15]:
base0(0: Nat)


Out[15]:
res14: Typ[Term] = Unit

In [16]:
base0(1: Nat)


Out[16]:
res15: Typ[Term] = Zero

In [17]:
base0(n + 1)


Out[17]:
res16: Typ[Term] = Zero

In [18]:
val Q = (NatTyp ->: Type).sym


Out[18]:
Q: Func[RepTerm[spire.math.SafeLong], Typ[Term]] = Q

In [19]:
recNatType(Zero).typ


Out[19]:
res18: Typ[Func[Func[Nat, Func[Typ[Term], Typ[Term]]], Func[Nat, Typ[Term]]]] = ((Nat.Typ → (𝒰  → 𝒰 )) → (Nat.Typ → 𝒰 ))

In [20]:
(n :-> A :-> Q(n)).typ


Out[20]:
res19: Typ[Func[Func[RepTerm[spire.math.SafeLong], Typ[Term]], Typ[Term]]] = ((Nat.Typ → 𝒰 ) → 𝒰 )

In [21]:
val step1arg = recNatType(Zero)(k :-> (A :-> Q(k)))


Out[21]:
step1arg: Func[Nat, Typ[Term]] = rec_{ Nat.Typ ; 𝒰  }(Zero)((k : Nat.Typ) ↦ (_ : 𝒰 ) ↦ Q(k))

In [22]:
step1arg.typ


Out[22]:
res21: Typ[Func[Nat, Typ[Term]]] = (Nat.Typ → 𝒰 )

In [23]:
val step0 = n :-> (Q :-> step1arg)


Out[23]:
step0: Func[RepTerm[spire.math.SafeLong], Func[Func[RepTerm[spire.math.SafeLong], Typ[Term]], Func[Nat, Typ[Term]]]] = (_ : Nat.Typ) ↦ (Q : (Nat.Typ → 𝒰 )) ↦ rec_{ Nat.Typ ; 𝒰  }(Zero)((k : Nat.Typ) ↦ (_ : 𝒰 ) ↦ Q(k))

In [24]:
step0.typ


Out[24]:
res23: Typ[Func[RepTerm[spire.math.SafeLong], Func[Func[RepTerm[spire.math.SafeLong], Typ[Term]], Func[Nat, Typ[Term]]]]] = (Nat.Typ → ((Nat.Typ → 𝒰 ) → (Nat.Typ → 𝒰 )))

In [25]:
val AreEqual = recNatNatType(base0)(step0)


Out[25]:
AreEqual: Func[Nat, Func[RepTerm[spire.math.SafeLong], Typ[Term]]] = rec_{ Nat.Typ ; (Nat.Typ → 𝒰 ) }(rec_{ Nat.Typ ; 𝒰  }(Unit)((_ : Nat.Typ) ↦ (_ : 𝒰 ) ↦ Zero))((_ : Nat.Typ) ↦ (Q : (Nat.Typ → 𝒰 )) ↦ rec_{ Nat.Typ ; 𝒰  }(Zero)((k : Nat.Typ) ↦ (_ : 𝒰 ) ↦ Q(k)))

In [26]:
AreEqual.typ


Out[26]:
res25: Typ[Func[Nat, Func[RepTerm[spire.math.SafeLong], Typ[Term]]]] = (Nat.Typ → (Nat.Typ → 𝒰 ))

In [27]:
AreEqual(0: Nat)(0: Nat)


Out[27]:
res26: Typ[Term] = Unit

In [28]:
AreEqual(0: Nat)(1: Nat)


Out[28]:
res27: Typ[Term] = Zero

In [29]:
AreEqual(0)(n)


Out[29]:
res28: Typ[Term] = rec_{ Nat.Typ ; 𝒰  }(Unit)((_ : Nat.Typ) ↦ (_ : 𝒰 ) ↦ Zero)(n)

In [30]:
AreEqual(n + 1)(0)


Out[30]:
res29: Typ[Term] = Zero

In [31]:
AreEqual(n + 1)(n + 1)


Out[31]:
res30: Typ[Term] = rec_{ Nat.Typ ; (Nat.Typ → 𝒰 ) }(rec_{ Nat.Typ ; 𝒰  }(Unit)((_ : Nat.Typ) ↦ (_ : 𝒰 ) ↦ Zero))((_ : Nat.Typ) ↦ (Q : (Nat.Typ → 𝒰 )) ↦ rec_{ Nat.Typ ; 𝒰  }(Zero)((k : Nat.Typ) ↦ (_ : 𝒰 ) ↦ Q(k)))(n)(n)

In [32]:
AreEqual(m + 1)(m + 1) == AreEqual(m)(m)


Out[32]:
res31: Boolean = true

In [33]:
val diagInd = induc(m :-> AreEqual(m)(m))


Out[33]:
diagInd: Func[Term, Func[FuncLike[Nat, Func[Term, Term]], FuncLike[Nat, Term]]] = ($nnx : Unit) ↦ ($xqn : ∏($nny : Nat.Typ){ (rec_{ Nat.Typ ; (Nat.Typ → 𝒰 ) }(rec_{ Nat.Typ ; 𝒰  }(Unit)((_ : Nat.Typ) ↦ (_ : 𝒰 ) ↦ Zero))((_ : Nat.Typ) ↦ (Q : (Nat.Typ → 𝒰 )) ↦ rec_{ Nat.Typ ; 𝒰  }(Zero)((k : Nat.Typ) ↦ (_ : 𝒰 ) ↦ Q(k)))($nny)($nny) → rec_{ Nat.Typ ; (Nat.Typ → 𝒰 ) }(rec_{ Nat.Typ ; 𝒰  }(Unit)((_ : Nat.Typ) ↦ (_ : 𝒰 ) ↦ Zero))((_ : Nat.Typ) ↦ (Q : (Nat.Typ → 𝒰 )) ↦ rec_{ Nat.Typ ; 𝒰  }(Zero)((k : Nat.Typ) ↦ (_ : 𝒰 ) ↦ Q(k)))($nny)($nny)) }) ↦ induc_{ Nat.Typ ; (m : Nat.Typ) ↦ rec_{ Nat.Typ ; (Nat.Typ → 𝒰 ) }(rec_{ Nat.Typ ; 𝒰  }(Unit)((_ : Nat.Typ) ↦ (_ : 𝒰 ) ↦ Zero))((_ : Nat.Typ) ↦ (Q : (Nat.Typ → 𝒰 )) ↦ rec_{ Nat.Typ ; 𝒰  }(Zero)((k : Nat.Typ) ↦ (_ : 𝒰 ) ↦ Q(k)))(m)(m) }($nnx)($xqn)

In [34]:
diagInd.typ


Out[34]:
res33: Typ[Func[Term, Func[FuncLike[Nat, Func[Term, Term]], FuncLike[Nat, Term]]]] = (Unit → (∏($nny : Nat.Typ){ (rec_{ Nat.Typ ; (Nat.Typ → 𝒰 ) }(rec_{ Nat.Typ ; 𝒰  }(Unit)((_ : Nat.Typ) ↦ (_ : 𝒰 ) ↦ Zero))((_ : Nat.Typ) ↦ (Q : (Nat.Typ → 𝒰 )) ↦ rec_{ Nat.Typ ; 𝒰  }(Zero)((k : Nat.Typ) ↦ (_ : 𝒰 ) ↦ Q(k)))($nny)($nny) → rec_{ Nat.Typ ; (Nat.Typ → 𝒰 ) }(rec_{ Nat.Typ ; 𝒰  }(Unit)((_ : Nat.Typ) ↦ (_ : 𝒰 ) ↦ Zero))((_ : Nat.Typ) ↦ (Q : (Nat.Typ → 𝒰 )) ↦ rec_{ Nat.Typ ; 𝒰  }(Zero)((k : Nat.Typ) ↦ (_ : 𝒰 ) ↦ Q(k)))($nny)($nny)) } → ∏(m : Nat.Typ){ rec_{ Nat.Typ ; (Nat.Typ → 𝒰 ) }(rec_{ Nat.Typ ; 𝒰  }(Unit)((_ : Nat.Typ) ↦ (_ : 𝒰 ) ↦ Zero))((_ : Nat.Typ) ↦ (Q : (Nat.Typ → 𝒰 )) ↦ rec_{ Nat.Typ ; 𝒰  }(Zero)((k : Nat.Typ) ↦ (_ : 𝒰 ) ↦ Q(k)))(m)(m) }))

In [36]:
AreEqual(2)(3)


Out[36]:
res35: Typ[Term] = Zero

In [37]:
diagInd(Star).dom


Out[37]:
res36: Typ[FuncLike[Nat, Func[Term, Term]]] = ∏($nny : Nat.Typ){ (rec_{ Nat.Typ ; (Nat.Typ → 𝒰 ) }(rec_{ Nat.Typ ; 𝒰  }(Unit)((_ : Nat.Typ) ↦ (_ : 𝒰 ) ↦ Zero))((_ : Nat.Typ) ↦ (Q : (Nat.Typ → 𝒰 )) ↦ rec_{ Nat.Typ ; 𝒰  }(Zero)((k : Nat.Typ) ↦ (_ : 𝒰 ) ↦ Q(k)))($nny)($nny) → rec_{ Nat.Typ ; (Nat.Typ → 𝒰 ) }(rec_{ Nat.Typ ; 𝒰  }(Unit)((_ : Nat.Typ) ↦ (_ : 𝒰 ) ↦ Zero))((_ : Nat.Typ) ↦ (Q : (Nat.Typ → 𝒰 )) ↦ rec_{ Nat.Typ ; 𝒰  }(Zero)((k : Nat.Typ) ↦ (_ : 𝒰 ) ↦ Q(k)))($nny)($nny)) }

In [38]:
diagInd(Star).dom == m ~>: (AreEqual(m)(m) ->: AreEqual(m)(m))


Out[38]:
res37: Boolean = true

In [39]:
val p = AreEqual(m)(m).sym


Out[39]:
p: Term = p

In [41]:
val diag = diagInd(Star)(m :~> (p :-> p))


Out[41]:
diag: FuncLike[Nat, Term] = induc_{ Nat.Typ ; (m : Nat.Typ) ↦ rec_{ Nat.Typ ; (Nat.Typ → 𝒰 ) }(rec_{ Nat.Typ ; 𝒰  }(Unit)((_ : Nat.Typ) ↦ (_ : 𝒰 ) ↦ Zero))((_ : Nat.Typ) ↦ (Q : (Nat.Typ → 𝒰 )) ↦ rec_{ Nat.Typ ; 𝒰  }(Zero)((k : Nat.Typ) ↦ (_ : 𝒰 ) ↦ Q(k)))(m)(m) }(Star)((m : Nat.Typ) ↦ (p : rec_{ Nat.Typ ; (Nat.Typ → 𝒰 ) }(rec_{ Nat.Typ ; 𝒰  }(Unit)((_ : Nat.Typ) ↦ (_ : 𝒰 ) ↦ Zero))((_ : Nat.Typ) ↦ (Q : (Nat.Typ → 𝒰 )) ↦ rec_{ Nat.Typ ; 𝒰  }(Zero)((k : Nat.Typ) ↦ (_ : 𝒰 ) ↦ Q(k)))(m)(m)) ↦ p)

In [42]:
diag.typ == n ~>: (AreEqual(n)(n))


Out[42]:
res41: Boolean = true

In [69]:
val target = n :~> (m :~> (("_" :: (n =:= m)) :-> AreEqual(n)(m)))


Out[69]:
target: FuncLike[RepTerm[spire.math.SafeLong], FuncLike[RepTerm[spire.math.SafeLong], Func[Equality[RepTerm[spire.math.SafeLong]], Typ[Term]]]] = (n : Nat.Typ) ↦ (m : Nat.Typ) ↦ (_ : n = m) ↦ rec_{ Nat.Typ ; (Nat.Typ → 𝒰 ) }(rec_{ Nat.Typ ; 𝒰  }(Unit)((_ : Nat.Typ) ↦ (_ : 𝒰 ) ↦ Zero))((_ : Nat.Typ) ↦ (Q : (Nat.Typ → 𝒰 )) ↦ rec_{ Nat.Typ ; 𝒰  }(Zero)((k : Nat.Typ) ↦ (_ : 𝒰 ) ↦ Q(k)))(n)(m)

In [70]:
val indEq = IdentityTyp.induc(NatTyp, target)


Out[70]:
indEq: Func[FuncLike[RepTerm[spire.math.SafeLong], Term], FuncLike[RepTerm[spire.math.SafeLong], FuncLike[RepTerm[spire.math.SafeLong], Func[Equality[RepTerm[spire.math.SafeLong]], Term]]]] = ($yrlo : ∏($ypvu : Nat.Typ){ rec_{ Nat.Typ ; (Nat.Typ → 𝒰 ) }(rec_{ Nat.Typ ; 𝒰  }(Unit)((_ : Nat.Typ) ↦ (_ : 𝒰 ) ↦ Zero))((_ : Nat.Typ) ↦ (Q : (Nat.Typ → 𝒰 )) ↦ rec_{ Nat.Typ ; 𝒰  }(Zero)((k : Nat.Typ) ↦ (_ : 𝒰 ) ↦ Q(k)))($ypvu)($ypvu) }) ↦ ($yrlp : Nat.Typ) ↦ ($yrlq : Nat.Typ) ↦ ($yrlr : $yrlp = $yrlq) ↦ induc_{ ($zzyq : Nat.Typ) ↦ ($zzyr : Nat.Typ) ↦ $zzyq = $zzyr ; (n : Nat.Typ) ↦ (m : Nat.Typ) ↦ (_ : n = m) ↦ rec_{ Nat.Typ ; (Nat.Typ → 𝒰 ) }(rec_{ Nat.Typ ; 𝒰  }(Unit)((_ : Nat.Typ) ↦ (_ : 𝒰 ) ↦ Zero))((_ : Nat.Typ) ↦ (Q : (Nat.Typ → 𝒰 )) ↦ rec_{ Nat.Typ ; 𝒰  }(Zero)((k : Nat.Typ) ↦ (_ : 𝒰 ) ↦ Q(k)))(n)(m) }($yrlo)($yrlr)

In [71]:
indEq.typ


Out[71]:
res70: Typ[Func[FuncLike[RepTerm[spire.math.SafeLong], Term], FuncLike[RepTerm[spire.math.SafeLong], FuncLike[RepTerm[spire.math.SafeLong], Func[Equality[RepTerm[spire.math.SafeLong]], Term]]]]] = (∏($ypvu : Nat.Typ){ rec_{ Nat.Typ ; (Nat.Typ → 𝒰 ) }(rec_{ Nat.Typ ; 𝒰  }(Unit)((_ : Nat.Typ) ↦ (_ : 𝒰 ) ↦ Zero))((_ : Nat.Typ) ↦ (Q : (Nat.Typ → 𝒰 )) ↦ rec_{ Nat.Typ ; 𝒰  }(Zero)((k : Nat.Typ) ↦ (_ : 𝒰 ) ↦ Q(k)))($ypvu)($ypvu) } → ∏($yrlp : Nat.Typ){ ∏($yrlq : Nat.Typ){ ($yrlp = $yrlq → rec_{ Nat.Typ ; (Nat.Typ → 𝒰 ) }(rec_{ Nat.Typ ; 𝒰  }(Unit)((_ : Nat.Typ) ↦ (_ : 𝒰 ) ↦ Zero))((_ : Nat.Typ) ↦ (Q : (Nat.Typ → 𝒰 )) ↦ rec_{ Nat.Typ ; 𝒰  }(Zero)((k : Nat.Typ) ↦ (_ : 𝒰 ) ↦ Q(k)))($yrlp)($yrlq)) } })

In [72]:
indEq.dom == m ~>: AreEqual(m)(m)


Out[72]:
res71: Boolean = true

In [73]:
indEq.dom == diag.typ


Out[73]:
res72: Boolean = true

In [74]:
indEq(diag).typ


Out[74]:
res73: Typ[FuncLike[RepTerm[spire.math.SafeLong], FuncLike[RepTerm[spire.math.SafeLong], Func[Equality[RepTerm[spire.math.SafeLong]], Term]]]] = ∏($yrlp : Nat.Typ){ ∏($yrlq : Nat.Typ){ ($yrlp = $yrlq → rec_{ Nat.Typ ; (Nat.Typ → 𝒰 ) }(rec_{ Nat.Typ ; 𝒰  }(Unit)((_ : Nat.Typ) ↦ (_ : 𝒰 ) ↦ Zero))((_ : Nat.Typ) ↦ (Q : (Nat.Typ → 𝒰 )) ↦ rec_{ Nat.Typ ; 𝒰  }(Zero)((k : Nat.Typ) ↦ (_ : 𝒰 ) ↦ Q(k)))($yrlp)($yrlq)) } }

In [75]:
indEq(diag)(m)(n)


Out[75]:
res74: Func[Equality[RepTerm[spire.math.SafeLong]], Term] = ($yrlr : m = n) ↦ induc_{ ($afaku : Nat.Typ) ↦ ($afakv : Nat.Typ) ↦ $afaku = $afakv ; (n : Nat.Typ) ↦ (m : Nat.Typ) ↦ (_ : n = m) ↦ rec_{ Nat.Typ ; (Nat.Typ → 𝒰 ) }(rec_{ Nat.Typ ; 𝒰  }(Unit)((_ : Nat.Typ) ↦ (_ : 𝒰 ) ↦ Zero))((_ : Nat.Typ) ↦ (Q : (Nat.Typ → 𝒰 )) ↦ rec_{ Nat.Typ ; 𝒰  }(Zero)((k : Nat.Typ) ↦ (_ : 𝒰 ) ↦ Q(k)))(n)(m) }(induc_{ Nat.Typ ; (m : Nat.Typ) ↦ rec_{ Nat.Typ ; (Nat.Typ → 𝒰 ) }(rec_{ Nat.Typ ; 𝒰  }(Unit)((_ : Nat.Typ) ↦ (_ : 𝒰 ) ↦ Zero))((_ : Nat.Typ) ↦ (Q : (Nat.Typ → 𝒰 )) ↦ rec_{ Nat.Typ ; 𝒰  }(Zero)((k : Nat.Typ) ↦ (_ : 𝒰 ) ↦ Q(k)))(m)(m) }(Star)((m : Nat.Typ) ↦ (p : rec_{ Nat.Typ ; (Nat.Typ → 𝒰 ) }(rec_{ Nat.Typ ; 𝒰  }(Unit)((_ : Nat.Typ) ↦ (_ : 𝒰 ) ↦ Zero))((_ : Nat.Typ) ↦ (Q : (Nat.Typ → 𝒰 )) ↦ rec_{ Nat.Typ ; 𝒰  }(Zero)((k : Nat.Typ) ↦ (_ : 𝒰 ) ↦ Q(k)))(m)(m)) ↦ p))($yrlr)

In [76]:
indEq(diag)(m)(n).typ == (m =:= n) ->: AreEqual(m)(n)


Out[76]:
res75: Boolean = true

In [77]:
indEq(diag).typ == m ~>: (n ~>: ((m =:= n) ->: AreEqual(m)(n)))


Out[77]:
res76: Boolean = true

In [79]:
indEq(diag)(0: Nat)(1: Nat).typ


Out[79]:
res78: Typ[Func[Equality[RepTerm[spire.math.SafeLong]], Term]] = (0 = 1 → Zero)

In [ ]: