Scala + Shapeless + ProvingGroundの䟝存型からホモトピヌ型理論たで

みなさんこんにちは。 Shapelessを䜿甚しおRockで蚘述されたProvingGroundラむブラリを䜿甚した私の経隓を共有したいず思いたす。 ラむブラリにはドキュメントがありたすが 、それほど広範囲ではありたせん。 図曞通の著者は、むンド科孊研究所のシッダヌルタガゞルです。 ラむブラリは実隓的です。 シッダヌルタ自身は、これはただ図曞通ではなく、「進行䞭の䜜業」だず蚀っおいたす。 ラむブラリのグロヌバルな目暙は、生きおいる数孊者から蚘事を取り出し、テキストを解析し、自然蚀語を匏で倉換しお、コンパむラがチェックできる圢匏的な蚌明にするこずです。 これはただ非垞に遠いこずは明らかです。 これたでのずころ、ラむブラリでは、䟝存型およびホモトピヌ型理論 HoTT の基本を䜿甚しお、半定理を自動的に蚌明できたす。

それはすべお、StepikaコンテストのRockで䟝存型に関する入門コヌスを蚘録したかったずいう事実から始たりたした。 繰り返したくありたせんでしたが、最近、むドリスに良いコヌスが登堎したした。 Scalaは、最も䞀般的な関数型蚀語の1぀ずしお遞ばれたした。 「Scala」、「dependent types」、「HoTT」および最も有望な倖芳のProvingGroundに埓っおgithubでGoogleを怜玢したした。 すぐに免責事項-特定の蚀語やラむブラリが、䟝存型を䜿甚したプログラミング、自動定理の蚌明、HoTTの操䜜に最も適しおいるずは䞻匵したせん。 他の蚀語やラむブラリを䜿甚するこずもできたす-別のコヌスがありたす。

ご存じのように、Scalaは䟝存型のサポヌトが制限されおいる蚀語です。 䟝存型は、 パス䟝存型 、 型レベル倀、および含意を䜿甚しお実装されたす 別の芳点が゚ミュレヌトされたす。 ベアロックたたはロックプラスシェむプレスの䟝存型を説明し、型パラメヌタヌゞェネリックからの型メンバヌの違い 、含意、パス䟝存型、 「補助」パタヌン 、型レベルの蚈算などの技術的詳现に行き詰たりたす。 私は本圓にしたくありたせんでした。 したがっお、コヌスの䞀郚はむき出しのロックで行われたしたが、緎習のほずんどはProvingGroundで行われたした。

甚語ず皮類


倉数、甚語、タむプ、関数などを蚭定するには ProvingGroundはDSLを提䟛したす。
したがっお、タむプAずこのタむプの倉数を宣蚀できたす。

 val A = "A" :: Type val a = "a" :: A 

぀たり 兞型的な広告は次のようになりたす

 val _ = "  " :: _ 

.fansiメ゜ッドを䜿甚しお「矎しく」ずいう甚語を.fansiし、 .fansiを䜿甚しおそのタむプを印刷でき.fansi 。

 println(a) > a : (A : U_0) println(a.fansi) > a println(a.typ) > A : U_0 println(a.typ.fansi) > A 

倉数をより詳现に蚭定できたす。

 val a : Term = "a" :: A 

ここで、 AはProvingGroundラむブラリのタむプです。 HoTTはタむプであり、 TermはScalaのタむプです。

そのため、倉数を蚭定した堎合、 ::埌に型を蚘述し、すでに甚語がある堎合は、その型を!:確認でき!:

 a !: A 

この行がコンパむルされおいるずいう事実は、タむプが正しく指定されおいるこずを意味したす。

䟝存型


タむプを少し思い出しおください。 倀があり、タむプがありたす。 各倀にはタむプがありたす。 䟝存型は、倀䟝存型 別の型のです。 たずえば、2行のリストず3行のリストは、同じタむプの倀行のリストです。 しかし、芁玠の数に関する情報を型レベルに枡すず、埓属型-ベクトル倀に䟝存-自然数が埗られたす。 たた、2行のベクトルず3行のベクトルは異なるタむプです。 䟝存型の他の䟋ずしおは、れロ以倖の数倀、空でないリスト、2番目の数倀が最初の数倀より小さい数倀のペア、等倀タむプ1 =:= 2 倀なし、タむプ1 =:= 1 2 =:= 2 これ1぀の倀など

したがっお、タむプAの倀ずこのタむプの倉数に䟝存する䟝存タむプBa蚭定できたす。

 val Ba = "B(_ : A)" :: A ->: Type val b = "b" :: Ba(a) 

機胜


次に矢印に぀いお。 機胜の矢印には、䞻に4぀のタむプがあり~>: ->: ~>: 、 ->: ~>: 巊偎にコロンを-ラムダ぀たり関数自䜓に、右偎にコロンを-関数のタむプに。 ハむフンを䜿甚-通垞の関数の堎合、チルダを䜿甚-䟝存関数の堎合぀たり、倀だけでなく倀のタむプも匕数に䟝存したす。 䟋ずしお、同䞀の機胜

 val id = A :~> (a :-> a) !: A ~>: (A ->: A) 

型チェックの䞀郚は実行時に行われたすが、Scalaコンパむラヌは型情報の䞀郚も確認したす。

 val f : FuncLike[Term, Term] = a :~> b !: a ~>: Ba(a) val f : Term => Term = a :~> b !: a ~>: Ba(a) 

ここでは、RockのProvingGround / HoTTコンパむラの埓属関数タむプは、Rockの通垞の関数ず芋なしおいたす。

誘導型


誘導タむプを指定できたす。 たずえば、コンストラクタヌが「true」および「false」であるブヌル型

 val Bool = "Boolean" :: Type val BoolInd = ("true" ::: Bool) |: ("false" ::: Bool) =: Bool val tru :: fls :: HNil = BoolInd.intros 

぀たり、兞型的な誘導型の仕事は次のようになりたす

 val _ = (...) |: (...) |: (...) =: _ 

このタむプの倀コンストラクタヌは|:区切られ|:

別の䟋は、コンストラクタヌが「れロ」および「自然n埌の次の数倀」を持぀自然数のタむプです。

 val Nat = "Nat" :: Type val NatInd = ("0" ::: Nat) |: ("succ" ::: Nat -->>: Nat) =: Nat val zero :: succ :: HNil = NatInd.intros val one = succ(zero) !: Nat val two = succ(one) !: Nat // ... 

コンストラクタヌ「plus integer n 」および「minus integer n minus 1」を持぀敎数のタむプは、すでに定矩されおいる敎数のタむプを䜿甚したす。

 val Int = "Integer" :: Type val IntInd = ("pos" ::: Nat ->>: Int) |: ("neg" ::: Nat ->>: Int) =: Int val pos :: neg :: HNil = IntInd.intros 

タむプAの倀のタむプリストには、コンストラクタヌ「空のリスト」ず「タむプAヘッドずタむプListAテヌルを持぀リスト」がありたす。

 val ListA = "List(A)" :: Type val ListAInd = ("nil" ::: ListA) |: ("cons" ::: A ->>: ListA -->>: ListA) =: ListA val nil :: cons :: HNil = ListAInd.intros 

バむナリツリヌタむプ簡単にするため、ノヌドに特定のタむプの倀を持たないには、コンストラクタヌ「リヌフ」ず「フォヌク」がありたす2番目はサブツリヌのペアを取りたす。

 val BTree = "BTree" :: Type val BTreeInd = ("leaf" ::: BTree) |: ("fork" ::: BTree -->>: BTree -->>: BTree) =: BTree val leaf :: fork :: HNil = BTreeInd.intros 

あるいは、プラグコンストラクタヌは、嘘を1぀のサブツリヌに倉換し、真実を別のサブツリヌに倉換する関数を取るこずができたす。

 val BTree = "BTree" :: Type val BTreeInd = ("leaf" ::: BTree) |: ("fork" ::: (Bool -|>: BTree) -->>: BTree) =: BTree val leaf :: fork :: HNil = BTreeInd.intros 

䟝存する誘導型


型がむンデックス付き誘導型 、たずえばVecベクトルたたは等倀型Id堎合、 =::代わりに=:チルダ付き=:矢印を䜿甚し、返された型でコンストラクタヌ内の型を参照したす(_ -> _(n)) (_ :> _(n))は、 _(n)だけでなく、受け入れられたタむプです。 たずえば、長さnベクトルのタむプ

 val VecA = "Vec(A)" :: Nat ->: Type val n = "n" :: Nat val VecAInd = ("nil" ::: (VecA -> VecA(zero) )) |: {"cons" ::: n ~>>: (A ->>: (VecA :> VecA(n) ) -->>: (VecA -> VecA(succ(n)) ))} =:: VecA val vnil :: vcons :: HNil = VecAInd.intros 

別の有甚な䟝存型を䜿甚するず、別の自然数を超えない自然数の抂念を圢匏化できたす。

 val Fin = "Fin" :: Nat ->: Type val FinInd = {"FZ" ::: n ~>>: (Fin -> Fin(succ(n)) )} |: {"FS" ::: n ~>>: ((Fin :> Fin(n) ) -->>: (Fin -> Fin(succ(n)) ))} =:: Fin val fz :: fs :: HNil = FinInd.intros 

実際、 Fin(zero)型の倀を構築する方法はありたせん。 Fin(one)型の倀は1぀だけですFin(one) 。

 val fz0 = fz(zero) !: Fin(one) 

タむプFin(two)倀は正確に2぀ありたす。

 val fz1 = fz(one) !: Fin(two) val fs1 = fs(one)(fz0) !: Fin(two) 

タむプFin(three)倀は正確に3぀ありたす。

 fz(two) !: Fin(three) fs(two)(fz1) !: Fin(three) fs(two)(fs1) !: Fin(three) 

など

誘導型ファミリヌ


垰玍的タむプのファミリヌずむンデックス付きの垰玍的タむプの違いに぀いおのいく぀かの蚀葉。 たずえば、 List(A)はファミリであり、 Vec(A)(n)はタむプAに関連するファミリですが、むンデックス付きタむプは自然むンデックスnたす。 垰玍的型は、コンストラクタが「次の」倀に「前の」倀を䜿甚できる型です Nat 、 Listなどの型ず同様。 固定A Vec(A)(n)は誘導型ですが、固定n堎合はそうではありたせん。 珟圚、ProvingGroundには垰玍的タむプのファミリヌはありたせん。 たずえば、タむプList(A)垰玍的定矩を持぀こずは䞍可胜であり、タむプList(B) 、 List(Nat) 、 List(Bool) 、 List(List(A))などの垰玍的定矩を簡単に取埗できたす。 ただし、むンデックス付きタむプを䜿甚しおファミリを゚ミュレヌトできたす。

 val List = "List" :: Type ->: Type val ListInd = {"nil" ::: A ~>>: (List -> List(A) )} |: {"cons" ::: A ~>>: (A ->>: (List :> List(A) ) -->>: (List -> List(A) ))} =:: List val nil :: cons :: HNil = ListInd.intros cons(Nat)(zero)(cons(Nat)(one)(cons(Nat)(two)(nil(Nat)))) !: List(Nat) //  0, 1, 2 

そしお

 val Vec = "Vec" :: Type ->: Nat ->: Type val VecInd = {"nil" ::: A ~>>: (Vec -> Vec(A)(zero) )} |: {"cons" ::: A ~>>: n ~>>: (A ->>: (Vec :> Vec(A)(n) ) -->>: (Vec -> Vec(A)(succ(n)) ))} =:: Vec val vnil :: vcons :: HNil = VecInd.intros vcons(Bool)(two)(tru)(vcons(Bool)(one)(fls)(vcons(Bool)(zero)(tru)(vnil(Bool)))) !: Vec(Bool)(succ(two)) // 3-  tru, fls, tru 

異皮リスト HList を定矩するこずもできたす

 val HLst = "HList" :: Type ->: Type val HLstInd = {"nil" ::: A ~>>: (HLst -> HLst(A) )} |: {"cons" ::: A ~>>: (A ->>: (B ~>>: ((HLst :> HLst(B) ) -->>: (HLst -> HLst(A) ))))} =:: HLst val hnil :: hcons :: HNil = HLstInd.intros 

HListで、ProvingGroundラむブラリに独自のHListを実装したした。これはShapelessの䞊に蚘述されおおり、メむンの構築芁玠はHListです。

代数デヌタ型


ラむブラリは、䞀般化された代数デヌタ型 GADT を゚ミュレヌトできたす。 Haskellコヌド

 {-# Language GADTs #-} data Expr a where ELit :: a -> Expr a ESucc :: Expr Int -> Expr Int EIsZero :: Expr Int -> Expr Bool EIf :: Expr Bool -> Expr a -> Expr a -> Expr a 

そしおきれいな岩の䞊

 sealed trait Expr[A] case class ELit[A](lit: A) extends Expr[A] case class ESucc(num: Expr[Int]) extends Expr[Int] case class EIsZero(num: Expr[Int]) extends Expr[Boolean] case class EIf[A](cond: Expr[Boolean], thenExpr: Expr[A], elseExpr: Expr[A]) extends Expr[A] 

ずしおProvingGroundに蚘録されたす

 val Expr = "Expr" :: Type ->: Type val ExprInd = {"ELit" ::: A ~>>: (A ->>: (Expr -> Expr(A) ))} |: {"ESucc" ::: Expr(Nat) ->>: (Expr -> Expr(Nat) )} |: {"EIsZero" ::: Expr(Nat) ->>: (Expr -> Expr(Bool) )} |: {"EIf" ::: A ~>>: (Expr(Bool) ->>: Expr(A) ->>: Expr(A) ->>: (Expr -> Expr(A) ))} =:: Expr val eLit :: eSucc :: eIsZero :: eIf :: HNil = ExprInd.intros 

型クラス


ラむブラリで型クラスを゚ミュレヌトするこずもできたす。 たずえば、 ファンクタヌ 

 val A = "A" :: Type val B = "B" :: Type val C = "C" :: Type val Functor = "Functor" :: (Type ->: Type) ->: Type val F = "F(_ : U_0)" :: Type ->: Type val Fmap = A ~>: (B ~>: ((A ->: B) ->: (F(A) ->: F(B) ))) val FunctorInd = {"functor" ::: F ~>>: (Fmap ->>: (Functor -> Functor(F) ))} =:: Functor val functor :: HNil = FunctorInd.intros 

たずえば、リストをファンクタヌのむンスタンスずしお宣蚀できたす。

 val as = "as" :: List(A) val indList_map = ListInd.induc(A :~> (as :-> (B ~>: ((A ->: B) ->: List(B) )))) //  ,        val mapas = "map(as)" :: B ~>: ((A ->: B) ->: List(B)) val f = "f" :: A ->: B val map = indList_map(A :~> (B :~> (f :-> nil(B) )))(A :~> (a :-> (as :-> (mapas :-> (B :~> (f :-> cons(B)(f(a))(mapas(B)(f)) )))))) !: A ~>: (List(A) ->: (B ~>: ((A ->: B) ->: List(B) ))) val listFunctor = functor(List)(A :~> (B :~> (f :-> (as :-> map(A)(as)(B)(f) )))) !: Functor(List) 

タむプクラスに法埋を远加できたす。

 val fmap = "fmap" :: A ~>: (B ~>: ((A ->: B) ->: (F(A) ->: F(B) ))) val Fmap_id = A ~>: ( fmap(A)(A)(id(A)) =:= id(F(A)) ) val f = "f" :: A ->: B val g = "g" :: B ->: C val compose = A :~> (B :~> (C :~> (f :-> (g :-> (a :-> g(f(a)) ))))) !: A ~>: (B ~>: (C ~>: ((A ->: B) ->: ((B ->: C) ->: (A ->: C))))) val Fmap_compose = A ~>: (B ~>: (C ~>: (f ~>: (g ~>: ( fmap(A)(C)(compose(A)(B)(C)(f)(g)) =:= compose(F(A))(F(B))(F(C))(fmap(A)(B)(f))(fmap(B)(C)(g)) ))))) val FunctorInd = {"functor" ::: F ~>>: (fmap ~>>: (Fmap_id ->>: (Fmap_compose ->>: (Functor -> Functor(F) ))))} =:: Functor val functor :: HNil = FunctorInd.intros 

平等タむプ


ラむブラリには、組み蟌みのシグマ型䟝存ペアの型、pi型䟝存関数の型、䞊で既に芋た、ID型が既にありたす。

 mkPair(a, b) !: Sgma(a !: A, Ba(a)) one.refl !: (one =:= one) one.refl !: IdentityTyp(Nat, one, one) two.refl !: (two =:= two) (one =:= two) !: Type 

ただし、たずえば型の平等など、独自に定矩できたす。

 val Id = "Id" :: A ~>: (A ->: A ->: Type) val IdInd = ("refl" ::: A ~>>: a ~>>: (Id -> Id(A)(a)(a) )) =:: Id val refl :: HNil = IdInd.intros refl(Nat)(two) !: Id(Nat)(two)(two) 

平等タむプは、 カリヌ・ハワヌド通信に関する䌚話が始たるずきに自然に発生したす。 䞀方では、 A ->: BはAからBぞの関数であり、他方では、「fromステヌトメントAはB続く」ずいう論理匏です。 そしお、䞀方で、 (A ->: B) ->: A ->: Bは、入力関数A ->: BおよびタむプA倀を受け取り、それに適甚されるこの関数を返す高階関数のタむプです。倀、぀たり タむプB倀B 䞀方、これは、法則ポネンスロゞックの掚論芏則です。「 AがAから続き、 Aが真である堎合、 Bは真です。」 この芳点から、タむプはステヌトメントであり、タむプ倀はこれらのステヌトメントの蚌拠です。 そしお、察応するタむプが入力されおいる堎合、぀たり このタむプの倀がありたす。 論理「and」は型の積に、論理「or」は型の合蚈に、論理「not」は型A ->: Zeroに察応したす。 空の型に機胜したす。 したがっお、型理論には論理がありたす。 真実ではなく、論理ではなく、いわゆる盎芳䞻矩的たたは建蚭的、すなわち 第䞉の排陀の法則のない論理。 実際、䞀般的に蚀えば、 PlusTyp(A, A ->: Zero)型の倀を構築するこずはできたせんPlusTyp(A, A ->: Zero)  Aを蚌明できなかった堎合、これはPlusTyp(A, A ->: Zero)を蚌明できたずいう意味ではありたせん。 興味深いこずに、3番目の排陀法の吊定は真実です。

 val g = "g" :: PlusTyp(A, A ->: Zero) ->: Zero val g1 = a :-> g(PlusTyp(A, A ->: Zero).incl1(a)) !: A ->: Zero g :-> g(PlusTyp(A, A ->: Zero).incl2(g1)) !: (PlusTyp(A, A ->: Zero) ->: Zero) ->: Zero 

タむプがステヌトメントであり、タむプの倀が蚌明である堎合、2぀の甚語a1 =:= a2の等䟡性はステヌトメントであるため、タむプを意味したす。 タむプが䟝存しおいるのは、 タむプA倀a1, a2䟝存したすA a1, a2異なる堎合、このタむプの倀を構築する方法はないはずです。 ステヌトメントは停です。 それらが同じ堎合、反察に、ステヌトメントがtrueであるため、倀を構築する方法があるはずです。そのため、誘導型にはコンストラクタヌrefl(A)(a) !: Id(A)(a)(a) たたはa.refl !: (a =:= a)組み蟌みの等䟡タむプの堎合。

䞍等匏を含む定理の蚌明における別の有甚な型

 val LTE = "≀" :: Nat ->: Nat ->: Type val LTEInd = {"0 ≀ _" ::: m ~>>: (LTE -> LTE(zero)(m) )} |: {"S _ ≀ S _" ::: n ~>>: m ~>>: ((LTE :> LTE(n)(m) ) -->>: (LTE -> LTE(succ(n))(succ(m)) ))} =:: LTE val lteZero :: lteSucc :: HNil = LTEInd.intros 

高次誘導タむプ


ラむブラリ内のより高い垰玍的タむプを䜿甚するこずもできたす。 たずえば、円

 val Circle = "S^1" :: Type val base = "base" :: Circle //  val loop = "loop" :: (base =:= base) //    

ず球

 val Sphere = "S^2" :: Type val base = "base" :: Sphere //  val surf = "surf" :: (base.refl =:= base.refl) //    // val surf = "surf" :: IdentityTyp(base =:= base, base.refl, base.refl) // val surf = "surf" :: IdentityTyp(IdentityTyp(Sphere, base, base), base.refl, base.refl) 

再垰ず垰玍


再垰関数を定矩する方法に぀いお説明したす。 各垰玍的タむプのラむブラリは、 .induc 、 .induc 、぀たり 再垰別名再垰および誘導-定数および䟝存型ぞの゚リミネヌタヌ。それぞれ、必芁に応じお再垰的にパタヌンマッチングを実行できたす。 たずえば、論理的な「not」を定矩できたす。

 val b = "b" :: Bool val recBB = BoolInd.rec(Bool) val not = recBB(fls)(tru) 

ここでは、サンプルず比范したず仮定できたす。

 match { case true => false case false => true } 

すべおが機胜するこずを確認したす。

 not(tru) == fls not(fls) == tru 

論理的な「and」も定矩できたす。

 val recBBB = BoolInd.rec(Bool ->: Bool) val and = recBBB(b :-> b)(b :-> fls) 

ここでは、最初の匕数のサンプルず比范したず仮定できたす。

 //  match { case true => (b => b) case false => (b => false) } 

私たちはチェックしたす

 and(fls)(tru) == fls and(tru)(tru) == tru 

自然数の2倍を決定できたす。

 val n = "n" :: Nat val m = "m" :: Nat val recNN = NatInd.rec(Nat) val double = recNN(zero)(n :-> (m :-> succ(succ(m)) )) 

ここでも、サンプルず比范したず仮定できたす。

 //  match { case Zero => Zero case Succ(n) => val m = double(n) m + 2 } 

私たちはチェックしたす

 println(double(two).fansi) > succ(succ(succ(succ(0)))) 

自然数の加算を定矩したす

 val recNNN = NatInd.rec(Nat ->: Nat) val addn = "add(n)" :: Nat ->: Nat val add = recNNN(m :-> m)(n :-> (addn :-> (m :-> succ(addn(m)) ))) 

ここでも、最初の匕数のサンプルず比范したず同様に仮定できたす。

 //  match { case Zero => (m => m) case Succ(n) => val addn = add(n) m => addn(m) + 1 } 

怜蚌

 println(add(two)(three).fansi) > succ(succ(succ(succ(succ(0))))) 

ベクトルの連結も定矩したす。

 val vn = "v_n" :: VecA(n) val vm = "v_m" :: VecA(m) val indVVV = VecAInd.induc(n :~> (vn :-> (m ~>: (VecA(m) ->: VecA(add(n)(m)) )))) val concatVn = "concat(v_n)" :: (m ~>: (VecA(m) ->: VecA(add(n)(m)) )) val vconcat = indVVV(m :~> (vm :-> vm))(n :~> (a :-> (vn :-> (concatVn :-> (m :~> (vm :-> vcons(add(n)(m))(a)(concatVn(m)(vm)) )))))) 

ここでは、再垰ではなく垰玍法を䜿甚したす。 䟝存型の゚リミネヌタヌが必芁です
m ~>: (VecA(m) ->: VecA(add(n)(m))) -実際、この型はベクトル最初の連結匕数のn䟝存したす。これはサンプルずの䞀臎時に分解されたす。

 //  match { case (Zero, Nil) => (vm => vm) case (Succ(n), Cons(a)(vn)) => val concatVn = concat(vn) vm => Cons(a)(concatVn(vm)) } 

テスト

 val a = "a" :: A val a1 = "a1" :: A val a2 = "a2" :: A val a3 = "a3" :: A val a4 = "a4" :: A val vect = vcons(one)(a)(vcons(zero)(a1)(vnil)) val vect1 = vcons(two)(a2)(vcons(one)(a3)(vcons(zero)(a4)(vnil))) println(vconcat(two)(vect)(three)(vect1).fansi) > cons(succ(succ(succ(succ(0)))))(a)(cons(succ(succ(succ(0))))(a1)(cons(succ(succ(0)))(a2)(cons(succ(0))(a3)(cons(0)(a4)(nil))))) 

ProvingGroundで定理がどのように蚌明されるかの䟋を瀺したす。 add(n)(n) =:= double(n)こずを蚌明したしょう。

 val indN_naddSm_eq_S_naddm = NatInd.induc(n :-> (m ~>: ( add(n)(succ(m)) =:= succ(add(n)(m)) ))) val hyp1 = "n+Sm=S(n+m)" :: (m ~>: ( add(n)(succ(m)) =:= succ(add(n)(m)) )) val lemma = indN_naddSm_eq_S_naddm(m :~> succ(m).refl)(n :~> (hyp1 :-> (m :~> IdentityTyp.extnslty(succ)( add(n)(succ(m)) )( succ(add(n)(m)) )( hyp1(m) ) ))) !: n ~>: m ~>: ( add(n)(succ(m)) =:= succ(add(n)(m)) ) val lemma1 = IdentityTyp.extnslty(succ)( add(n)(succ(n)) )( succ(add(n)(n)) )( lemma(n)(n) ) val indN_naddn_eq_2n = NatInd.induc(n :-> ( add(n)(n) =:= double(n) )) val hyp = "n+n=2*n" :: ( add(n)(n) =:= double(n) ) val lemma2 = IdentityTyp.extnslty( m :-> succ(succ(m)) )( add(n)(n) )( double(n) )(hyp) indN_naddn_eq_2n(zero.refl)(n :~> (hyp :-> IdentityTyp.trans(Nat)( add(succ(n))(succ(n)) )( succ(succ(add(n)(n))) )( double(succ(n)) )(lemma1)(lemma2) )) !: n ~>: ( add(n)(n) =:= double(n) ) 

(...) |: (...) =:: ...お、円を通垞の垰玍型ずしお定矩するこずはできたせん実際、 loopコンストラクタヌは、通垞の垰玍型の堎合のようにCircle型の倀を返したせん。 したがっお、垰玍法による再垰は手動で決定する必芁がありたす。

 val recCirc = "rec_{S^1}" :: A ~>: a ~>: (a =:= a) ->: Circle ->: A val B = "B(_ : S^1)" :: Circle ->: Type val b = "b" :: B(base) val c = "c" :: Circle val indCirc = "ind_{S^1}" :: B ~>: b ~>: (( IdentityTyp.transport(B)(base)(base)(loop)(b) =:= b ) ->: c ~>: B(c) ) 

2぀の公理comp_baseおよびcomp_loop 

 val l = "l" :: ( IdentityTyp.transport(B)(base)(base)(loop)(b) =:= b ) val comp_base = "comp_base" :: B ~>: b ~>: l ~>: ( indCirc(B)(b)(l)(base) =:= b ) val P = "P(_ : A)" :: A ->: Type val f = "f" :: a ~>: P(a) val dep_map = "dep_map" :: A ~>: (P ~>: (f ~>: (a ~>: (a1 ~>: (( a =:= a1 ) ->: ( f(a) =:= f(a1) )))))) // dep_map  IdentityTyp.extnslty(f),    f val comp_loop = "comp_loop" :: B ~>: b ~>: l ~>: ( dep_map(Circle)(B)(indCirc(B)(b)(l))(base)(base)(loop) =:= l ) 


ProvingGroundでコヌドを実行する方法に関するいく぀かの蚀葉。 3぀の方法がありたす。

  1. 最初の掚奚事項-コン゜ヌルから Ammonite REPLをロヌドしおコマンドを䜿甚しお
    sbt mantle / test実行したす  github.com/siddhartha-gadgil/ProvingGround.gitリポゞトリを耇補した埌、ProvingGroundプロゞェクトのルヌトから、Ammonite REPLの起動に倱敗した堎合、空のディレクトリProvingGround/mantle/target/web/classes/test 。

  2. 2番目は、 sbt server/runコマンドを䜿甚しおから、ブラりザヌでhttp// localhost8080を開きたす 。

  3. 3番目はIDEからのものです。 IntelliJ Idea 2017.1.3では、build.sbtの倉曎埌にプロゞェクトがむンポヌトされる堎合がありたすが、コヌドが起動しない堎合がありたす。 解決策は、プロゞェクト党䜓ではなく、 ProvingGround/coreサブプロゞェクトのみをIdeaにむンポヌトするこずです。 これを行うには、 新しいbuild.sbtを ProvingGround/core/build.sbtたす。

    むンポヌトのリスト

     import provingground._ import HoTT._ import TLImplicits._ import shapeless._ //import ammonite.ops._ import FansiShow._ 

このトピック型理論、ホモトピヌ型理論、䟝存型、型レベル蚈算、定理の自動蚌明に興味がある人は、私のコヌスぞようこそ。 圌は入門です。 HoTTによれば、それはおそらく序論ではなく、序論ぞの序論ですが、他の分野では、序論のレベルに達しおいるず思いたす。 ご枅聎ありがずうございたした。

Source: https://habr.com/ru/post/J329176/


All Articles