Agdaで怜蚌枈みのQuickSort

芪愛なるhabrayuzerさん、こんにちは

型付きラムダ蚈算、぀たり䟝存型に関するいく぀かの本を読んだ埌、興味深いパタヌンを芋たしたどこでも、最初の䟋は゜ヌトされたリスト型の定矩です。 すべおは問題ありたせんが、この定矩を超えるものはありたせんでした。 そこで、このギャップを芋぀けお、リストを取埗しお別のリストず2぀の蚌明を返す関数を実装したした。 1぀は結果が入力の順列であるこずを蚌明し、もう1぀は結果が゜ヌトされたリストであるこずを蚌明したす。


正匏な説明



このパヌトでは、埌で䜿甚する䞻なタむプずいく぀かの補助機胜を瀺したす。 たた、Agdaの興味深い構文䞊の魅力もここに瀺されたす。 Agdaにあたり詳しくない人のために、䌚議SPbHUG / FProg 2012-07 で Jan Malakhovskyのビデオ/スラむドを芋るこずをお勧めしたす。 たたは、Agda Webサむト 倧きくはありたせんたたはこのチュヌトリアル からマニュアルをめくる。

リスト定矩

data List {a} (A : Set a) : Set a where [] : List A _∷_ : (x : A) (xs : List A) → List A [_] : ∀ {a} {A : Set a} → A → List A [ x ] = x ∷ [] _++_ : ∀ {a} {A : Set a} → List A → List A → List A [] ++ ys = ys (x ∷ xs) ++ ys = x ∷ (xs ++ ys) 

ここにリストがありたす。 暙準ラむブラリから取埗した定矩。 ご芧のずおり、リストアむテムは、任意のタむプの倀、さらにはタむプやタむプのタむプなどの倀にするこずができたす。 これは、高次ポリモヌフィズムの䜿甚により可胜です。レベルを担圓するパラメヌタヌが導入されたす。぀たり、通垞の型はSet 0型、 Set 0はSet 1型などです。
たた、この定矩では、Agdaで挔算子がどのように宣蚀されおいるか、぀たり匕数がある堎所にアンダヌスコアを䜿甚しお宣蚀できたす。 このメ゜ッドを䜿甚するず、単䞀の芁玠[_]からリストを返す関数など、さたざたな非垞に興味深い圢匏を定矩できるこずに泚意しおください。

すべおの挔算子アンダヌスコア付きのコンビネヌタに察しお、優先床ず結合性を指定できるこずに泚意しおください。 たた、Agdaでは、スペヌスずブラケット䞞括匧および䞭括匧のないUnicodeシヌケンスは甚語です。
たた、括匧ず䞭括匧にも泚意を払う必芁がありたす。型を瀺す䞭括匧は、この匕数が暗黙的であり、コンパむラヌによっお出力されるこずを瀺したす。

「゜ヌト枈みリスト」ず入力したす

 data Sorted {A} (_≀_ : A → A → Set) : List A → Set where nil : Sorted _≀_ [] one : {x : A} → Sorted _≀_ [ x ] two : {x : A} → ∀ {yl} → x ≀ y → Sorted _≀_ (y ∷ l) → Sorted _≀_ (x ∷ y ∷ l) 

これは、゜ヌトされたリストの述語の定矩です。 蚭蚈者は公理ず芋なされるべきです。 nilの公理ず空のリストず1぀の芁玠からのリストが゜ヌトされるずいう公理がありたす。 たた、 䞊べ替えられた型は、順序を担圓する述語_≀_に䟝存しおいるこずがわかりたす 。これは、比范関数のようなものですが、䟝存型です匕数は通垞の型の倀であり、結果は倀が蚌明である型です。 公理2は、 x≀y  x≀yが型であり、型x≀yの倀がx≀yであるずいう蚌明がある堎合 、 カリヌ-ハワヌド同型を参照ずその蚌明がある堎合、 、先頭がyのリストが゜ヌトされるようにこの蚌明はSorted_≀_y∷l型の倀です 、リストx∷y∷lも゜ヌトされたす。

タむプ「順列」

 data Permutation {A} : List A → List A → Set where refl : ∀ {l} → Permutation ll perm : ∀ {l} l₁ x₁ x₂ l₂ → Permutation l (l₁ ++ x₂ ∷ x₁ ∷ l₂) → Permutation l (l₁ ++ x₁ ∷ x₂ ∷ l₂) 

タむプ述語「順列」。 匕数は2぀のリストです。 導入された公理は次のずおりです。refl-リストはそれ自䜓の順列です。 perm-あるリストlが別のリストlの順列であるこずの蚌明がある堎合この蚌明は型permutation ll₁++x₂∷x₁∷l₂の倀です 、任意の2぀のリストを䞊べ替える堎合芁玠を配眮するず、新しいリストは最初のリストの順列であるこずがわかりたす。

「量」ず入力したす

 data _⊎_ {ab} (A : Set a) (B : Set b) : Set (a ⊔ b) where inj₁ : (x : A) → A ⊎ B inj₂ : (y : B) → A ⊎ B 

さお、ここではすべおが単玔です-それは䟝存型ではなく-Haskellのいずれかの類䌌物です。

補品の皮類

 record Σ {ab} (A : Set a) (B : A → Set b) : Set (a ⊔ b) where constructor _,_ field proj₁ : A proj₂ : B proj₁ syntax Σ A (λ x → B) = Σ[ x ∶ A ] B _×_ : ∀ {ab} (A : Set a) (B : Set b) → Set (a ⊔ b) A × B = Σ[ _ ∶ A ] B 

これはタプルの類䌌物です。 この型はコンストラクタを1぀しか持぀こずができないため、 レコヌドが䜿甚されたす。 この定矩は䟝存型を䜿甚したす。最初の芁玠は特定の倀であり、2番目はこの芁玠に察する䜕らかの述語の実行の蚌明です。 しかし、もちろん、そのように䜿甚する必芁はありたせん。通垞のタプルのように _×_を介しお実行できたす-芁玠間の䟝存関係は無芖されたす。 構文を䜿甚するず、単玔な可胜性が少ない堎合に新しい構文構成を定矩できたす。

゜ヌト機胜

 sort : {A : Set} {_≀_ : A → A → Set} → (∀ xy → (x ≀ y) ⊎ (y ≀ x)) → (l : List A) → Σ[ l' ∶ List A ] (Sorted _≀_ l' × Permutation l l') 

最埌に、゜ヌト関数のタむプを説明したすこの関数は、順序を決定する暗黙の述語、および入力倀に察しお、1番目が2番目より倧きい、たたは2番目が1番目より倧きいずいう蚌明を返す関数を受け入れたす。 読者は、゜ヌトされたリスト結果の蚌明を䜜成するためにこの関数が䜿甚されるず掚枬したず思いたす。 たた、もちろん、入力パラメヌタヌの1぀は゜ヌトされるリストです。
゜ヌト関数は、リストず2぀の蚌明゜ヌトず順列を返したす。

゜ヌト機胜の実装


もちろん、ここではこの関数の実装はありたせん。コヌドを衚瀺しおすみたせんが、自分で説明しおすみたせん。 したがっお、゜ヌト関数を䜜成するずきに必芁ないく぀かの補助関数の蚌明実装を提䟛したす。
動䜜する゜ヌスはここにありたす。
䜿甚されるAgda-2.3.1および暙準ラむブラリ-0.6
 {-# OPTIONS --no-termination-check #-} module QuickSort where open import IO.Primitive using () renaming (putStrLn to putCoStrLn) open import Data.String using (toCostring; String) renaming (_++_ to _+s+_) open import Data.List open import Data.Nat open import Data.Nat.Show open import Data.Sum open import Data.Product open import Relation.Binary.Core open import Function data Sorted {A} (_≀_ : A → A → Set) : List A → Set where nil : Sorted _≀_ [] one : {x : A} → Sorted _≀_ [ x ] two : {x : A} → ∀ {yl} → x ≀ y → Sorted _≀_ (y ∷ l) → Sorted _≀_ (x ∷ y ∷ l) data Permutation {A} : List A → List A → Set where refl : ∀ {l} → Permutation ll perm : ∀ {l} l₁ x₁ x₂ l₂ → Permutation l (l₁ ++ x₂ ∷ x₁ ∷ l₂) → Permutation l (l₁ ++ x₁ ∷ x₂ ∷ l₂) ≡-elim : ∀ {l} {A : Set l} {xy : A} → x ≡ y → (P : A → Set l) → P x → P y ≡-elim refl _ p = p ≡-sym : ∀ {l} {A : Set l} {xy : A} → x ≡ y → y ≡ x ≡-sym refl = refl ≡-trans : ∀ {l} {A : Set l} {xyz : A} → x ≡ y → y ≡ z → x ≡ z ≡-trans refl refl = refl ++-assoc : ∀ {l} {A : Set l} (l₁ l₂ l₃ : List A) → (l₁ ++ l₂) ++ l₃ ≡ l₁ ++ (l₂ ++ l₃) ++-assoc [] l₂ l₃ = refl ++-assoc (h ∷ t) l₂ l₃ = ≡-elim (≡-sym $ ++-assoc t l₂ l₃) (λ x → h ∷ x ≡ h ∷ t ++ (l₂ ++ l₃)) refl decNat : (xy : ℕ) → (x ≀ y) ⊎ (y ≀ x) decNat zero y = inj₁ z≀n decNat (suc x) (suc y) with decNat xy ... | inj₁ p = inj₁ (s≀sp) ... | inj₂ p = inj₂ (s≀sp) decNat (suc x) zero = inj₂ z≀n perm-trans : ∀ {A} {l₁ l₂ l₃ : List A} → Permutation l₁ l₂ → Permutation l₂ l₃ → Permutation l₁ l₃ perm-trans p refl = p perm-trans p₁ (perm l₁ x₁ x₂ l₂ p₂) = perm l₁ x₁ x₂ l₂ $ perm-trans p₁ p₂ perm-sym : ∀ {A} {l₁ l₂ : List A} → Permutation l₁ l₂ → Permutation l₂ l₁ perm-sym refl = refl perm-sym (perm l₁ x₁ x₂ l₂ p) = perm-trans (perm l₁ x₂ x₁ l₂ refl) (perm-sym p) perm-del-ins-r : ∀ {A} (l₁ : List A) (x : A) (l₂ l₃ : List A) → Permutation (l₁ ++ x ∷ l₂ ++ l₃) (l₁ ++ l₂ ++ x ∷ l₃) perm-del-ins-r l₁ x [] l₃ = refl perm-del-ins-r l₁ x (h ∷ t) l₃ = perm-trans p₀ p₅ where p₀ : Permutation (l₁ ++ x ∷ h ∷ t ++ l₃) (l₁ ++ h ∷ x ∷ t ++ l₃) p₀ = perm l₁ hx (t ++ l₃) refl p₁ : Permutation ((l₁ ++ [ h ]) ++ x ∷ t ++ l₃) ((l₁ ++ [ h ]) ++ t ++ x ∷ l₃) p₁ = perm-del-ins-r (l₁ ++ [ h ]) xt l₃ p₂ : (l₁ ++ [ h ]) ++ t ++ x ∷ l₃ ≡ l₁ ++ h ∷ t ++ x ∷ l₃ p₂ = ++-assoc l₁ [ h ] (t ++ x ∷ l₃) p₃ : (l₁ ++ [ h ]) ++ x ∷ t ++ l₃ ≡ l₁ ++ h ∷ x ∷ t ++ l₃ p₃ = ++-assoc l₁ [ h ] (x ∷ t ++ l₃) p₄ : Permutation ((l₁ ++ [ h ]) ++ x ∷ t ++ l₃) (l₁ ++ h ∷ t ++ x ∷ l₃) p₄ = ≡-elim p₂ (λ y → Permutation ((l₁ ++ [ h ]) ++ x ∷ t ++ l₃) y) p₁ p₅ : Permutation (l₁ ++ h ∷ x ∷ t ++ l₃) (l₁ ++ h ∷ t ++ x ∷ l₃) p₅ = ≡-elim p₃ (λ y → Permutation y (l₁ ++ h ∷ t ++ x ∷ l₃)) p₄ perm-del-ins-l : ∀ {A} (l₁ l₂ : List A) (x : A) (l₃ : List A) → Permutation (l₁ ++ l₂ ++ x ∷ l₃) (l₁ ++ x ∷ l₂ ++ l₃) perm-del-ins-l l₁ l₂ x l₃ = perm-sym $ perm-del-ins-r l₁ x l₂ l₃ perm-++ : ∀ {A} {x₁ y₁ x₂ y₂ : List A} → Permutation x₁ y₁ → Permutation x₂ y₂ → Permutation (x₁ ++ x₂) (y₁ ++ y₂) perm-++ refl refl = refl perm-++ (perm {x₁} l₁ e₁ e₂ l₂ p) (refl {z₂}) = perm-trans p₅ p₇ where p₁ : Permutation (x₁ ++ z₂) ((l₁ ++ e₂ ∷ e₁ ∷ l₂) ++ z₂) p₁ = perm-++ p refl p₂ : (l₁ ++ e₂ ∷ e₁ ∷ l₂) ++ z₂ ≡ l₁ ++ (e₂ ∷ e₁ ∷ l₂) ++ z₂ p₂ = ++-assoc l₁ (e₂ ∷ e₁ ∷ l₂) z₂ p₃ : l₁ ++ (e₂ ∷ e₁ ∷ l₂) ++ z₂ ≡ l₁ ++ e₂ ∷ (e₁ ∷ l₂) ++ z₂ p₃ = ≡-elim (++-assoc [ e₂ ] (e₁ ∷ l₂) z₂) (λ x → l₁ ++ (e₂ ∷ e₁ ∷ l₂) ++ z₂ ≡ l₁ ++ x) refl p₄ : l₁ ++ e₂ ∷ (e₁ ∷ l₂) ++ z₂ ≡ l₁ ++ e₂ ∷ e₁ ∷ l₂ ++ z₂ p₄ = ≡-elim (++-assoc [ e₁ ] l₂ z₂) (λ x → l₁ ++ e₂ ∷ (e₁ ∷ l₂) ++ z₂ ≡ l₁ ++ e₂ ∷ x) refl g₂ : (l₁ ++ e₁ ∷ e₂ ∷ l₂) ++ z₂ ≡ l₁ ++ (e₁ ∷ e₂ ∷ l₂) ++ z₂ g₂ = ++-assoc l₁ (e₁ ∷ e₂ ∷ l₂) z₂ g₃ : l₁ ++ (e₁ ∷ e₂ ∷ l₂) ++ z₂ ≡ l₁ ++ e₁ ∷ (e₂ ∷ l₂) ++ z₂ g₃ = ≡-elim (++-assoc [ e₁ ] (e₂ ∷ l₂) z₂) (λ x → l₁ ++ (e₁ ∷ e₂ ∷ l₂) ++ z₂ ≡ l₁ ++ x) refl g₄ : l₁ ++ e₁ ∷ (e₂ ∷ l₂) ++ z₂ ≡ l₁ ++ e₁ ∷ e₂ ∷ l₂ ++ z₂ g₄ = ≡-elim (++-assoc [ e₂ ] l₂ z₂) (λ x → l₁ ++ e₁ ∷ (e₂ ∷ l₂) ++ z₂ ≡ l₁ ++ e₁ ∷ x) refl p₅ : Permutation (x₁ ++ z₂) (l₁ ++ e₂ ∷ e₁ ∷ l₂ ++ z₂) p₅ = ≡-elim (≡-trans p₂ $ ≡-trans p₃ p₄) (Permutation (x₁ ++ z₂)) p₁ p₆ : Permutation (l₁ ++ e₂ ∷ e₁ ∷ l₂ ++ z₂) (l₁ ++ e₁ ∷ e₂ ∷ l₂ ++ z₂) p₆ = perm l₁ e₁ e₂ (l₂ ++ z₂) refl p₇ : Permutation (l₁ ++ e₂ ∷ e₁ ∷ l₂ ++ z₂) ((l₁ ++ e₁ ∷ e₂ ∷ l₂) ++ z₂) p₇ = ≡-elim (≡-sym $ ≡-trans g₂ $ ≡-trans g₃ g₄) (Permutation (l₁ ++ e₂ ∷ e₁ ∷ l₂ ++ z₂)) p₆ perm-++ {_} {x₁} {y₁} .{_} .{_} p₁ (perm {x₂} l₁ e₁ e₂ l₂ p₂) = ≡-elim p₇ (Permutation (x₁ ++ x₂)) p₆ where p' : Permutation (x₁ ++ x₂) (y₁ ++ l₁ ++ e₂ ∷ e₁ ∷ l₂) p' = perm-++ p₁ p₂ p₃ : y₁ ++ l₁ ++ e₂ ∷ e₁ ∷ l₂ ≡ (y₁ ++ l₁) ++ e₂ ∷ e₁ ∷ l₂ p₃ = ≡-sym $ ++-assoc y₁ l₁ (e₂ ∷ e₁ ∷ l₂) p₄ : Permutation (x₁ ++ x₂) ((y₁ ++ l₁) ++ e₂ ∷ e₁ ∷ l₂) p₄ = ≡-elim p₃ (Permutation (x₁ ++ x₂)) p' p₅ : Permutation ((y₁ ++ l₁) ++ e₂ ∷ e₁ ∷ l₂) ((y₁ ++ l₁) ++ e₁ ∷ e₂ ∷ l₂) p₅ = perm (y₁ ++ l₁) e₁ e₂ l₂ refl p₆ : Permutation (x₁ ++ x₂) ((y₁ ++ l₁) ++ e₁ ∷ e₂ ∷ l₂) p₆ = perm-trans p₄ p₅ p₇ : (y₁ ++ l₁) ++ e₁ ∷ e₂ ∷ l₂ ≡ y₁ ++ l₁ ++ e₁ ∷ e₂ ∷ l₂ p₇ = ++-assoc y₁ l₁ (e₁ ∷ e₂ ∷ l₂) ++-[] : ∀ {l} {A : Set l} (l : List A) → l ++ [] ≡ l ++-[] [] = refl ++-[] (h ∷ t) = ≡-trans p₀ p₁ where p₀ : (h ∷ t) ++ [] ≡ h ∷ t ++ [] p₀ = ++-assoc [ h ] t [] p₁ : h ∷ t ++ [] ≡ h ∷ t p₁ = ≡-elim (++-[] t) (λ x → h ∷ t ++ [] ≡ h ∷ x) refl data ConstrainedList {A} (P : A → Set) : List A → Set where [] : ConstrainedList P [] _∷_ : {x : A} {xs : List A} (p : P x) → ConstrainedList P xs → ConstrainedList P (x ∷ xs) infix 2 _∈_ data _∈_ {A} : A → List A → Set where exact : ∀ ht → h ∈ h ∷ t cons : ∀ h {xl} → x ∈ l → x ∈ h ∷ l create-∈ : ∀ {A} (l₁ : List A) (x : A) (l₂ : List A) → x ∈ (l₁ ++ x ∷ l₂) create-∈ [] x l₂ = exact x l₂ create-∈ (h₁ ∷ t₁) x l₂ = cons h₁ $ create-∈ t₁ x l₂ perm-∈ : ∀ {A l l'} {x : A} → x ∈ l → Permutation l' l → x ∈ l' perm-∈ p refl = p perm-∈ {A} .{l₁ ++ x₁ ∷ x₂ ∷ l₂} {l'} {x} p₁ (perm l₁ x₁ x₂ l₂ p₂) = perm-∈ (loop l₁ x₁ x₂ l₂ p₁) p₂ where loop : ∀ l₁ x₁ x₂ l₂ → x ∈ l₁ ++ x₁ ∷ x₂ ∷ l₂ → x ∈ l₁ ++ x₂ ∷ x₁ ∷ l₂ loop [] .x x₂ l₂ (exact .x .(x₂ ∷ l₂)) = cons x₂ $ exact x l₂ loop [] .x₁ .x .l₂ (cons x₁ (exact .x l₂)) = exact x (x₁ ∷ l₂) loop [] .x₁ .x₂ l₂ (cons x₁ (cons x₂ p)) = cons x₂ $ cons x₁ p loop (.x ∷ t₁) x₁ x₂ l₂ (exact .x .(t₁ ++ x₁ ∷ x₂ ∷ l₂)) = exact x (t₁ ++ x₂ ∷ x₁ ∷ l₂) loop (.h₁ ∷ t₁) x₁ x₂ l₂ (cons h₁ p) = cons h₁ $ loop t₁ x₁ x₂ l₂ p constr-∈ : ∀ {A l} {x : A} → ∀ {P} → ConstrainedList P l → x ∈ l → P x constr-∈ [] () constr-∈ (p ∷ _) (exact _ _) = p constr-∈ (_ ∷ cl) (cons _ p) = constr-∈ cl p sortedHelper₂ : ∀ {A _≀_} {h : A} → ∀ {l'} → Sorted _≀_ l' → ∀ {l} → Permutation ll' → ConstrainedList (λ x → x ≀ h) l → ∀ {g'} → Sorted _≀_ (h ∷ g') → Sorted _≀_ (l' ++ h ∷ g') sortedHelper₂ {_} {_≀_} {h} {l'} sl' pll' cl {g'} sg' = loop [] l' refl sl' where loop : ∀ l₁ l₂ → l₁ ++ l₂ ≡ l' → Sorted _≀_ l₂ → Sorted _≀_ (l₂ ++ h ∷ g') loop _ .[] _ nil = sg' loop l₁ .(x ∷ []) p (one {x}) = two (constr-∈ cl $ perm-∈ x∈l' pll') sg' where x∈l' : x ∈ l' x∈l' = ≡-elim p (λ l → x ∈ l) (create-∈ l₁ x []) loop l₁ .(x ∷ y ∷ l) p≡ (two {x} {y} {l} x≀y ps) = two x≀y $ loop (l₁ ++ [ x ]) (y ∷ l) p' ps where p' : (l₁ ++ [ x ]) ++ y ∷ l ≡ l' p' = ≡-trans (++-assoc l₁ [ x ] (y ∷ l)) p≡ sortedHelper₁ : ∀ {A _≀_} {h : A} → ∀ {l'} → Sorted _≀_ l' → ∀ {l} → Permutation ll' → ConstrainedList (λ x → x ≀ h) l → ∀ {g'} → Sorted _≀_ g' → ∀ {g} → Permutation gg' → ConstrainedList (λ x → h ≀ x) g → Sorted _≀_ (l' ++ h ∷ g') sortedHelper₁ sl' pll' cl nil _ _ = sortedHelper₂ sl' pll' cl one sortedHelper₁ sl' pll' cl {h ∷ t} sg' pgg' cg = sortedHelper₂ sl' pll' cl $ two (constr-∈ cg $ perm-∈ (exact ht) pgg') sg' quickSort : {A : Set} {_≀_ : A → A → Set} → (∀ xy → (x ≀ y) ⊎ (y ≀ x)) → (l : List A) → Σ[ l' ∶ List A ] (Sorted _≀_ l' × Permutation l l') quickSort _ [] = [] , nil , refl quickSort {A} {_≀_} _≀?_ (h ∷ t) = loop t [] [] [] [] refl where loop : ∀ ilg → ConstrainedList (λ x → x ≀ h) l → ConstrainedList (λ x → h ≀ x) g → Permutation t ((l ++ g) ++ i) → Σ[ l' ∶ List A ] (Sorted _≀_ l' × Permutation (h ∷ t) l') loop [] lg cl cg p = l' ++ h ∷ g' , sortedHelper₁ sl' pll' cl sg' pgg' cg , perm-trans p₃ p₄ where lSort = quickSort _≀?_ l gSort = quickSort _≀?_ g l' = proj₁ lSort g' = proj₁ gSort sl' = proj₁ $ proj₂ lSort sg' = proj₁ $ proj₂ gSort pll' = proj₂ $ proj₂ lSort pgg' = proj₂ $ proj₂ gSort p₁ : Permutation (l ++ g) (l' ++ g') p₁ = perm-++ pll' pgg' p₂ : Permutation t (l' ++ g') p₂ = perm-trans (≡-elim (++-[] (l ++ g)) (λ x → Permutation tx) p) p₁ p₃ : Permutation (h ∷ t) (h ∷ l' ++ g') p₃ = perm-++ (refl {_} {[ h ]}) p₂ p₄ : Permutation (h ∷ l' ++ g') (l' ++ h ∷ g') p₄ = perm-del-ins-r [] hl' g' loop (h' ∷ t) lg cl cg p with h' ≀? h ... | inj₁ h'≀h = loop t (h' ∷ l) g (h'≀h ∷ cl) cg (perm-trans p p') where p' : Permutation ((l ++ g) ++ h' ∷ t) (h' ∷ (l ++ g) ++ t) p' = perm-del-ins-l [] (l ++ g) h' t ... | inj₂ h≀h' = loop tl (h' ∷ g) cl (h≀h' ∷ cg) (perm-trans p p') where p₁ : l ++ g ++ h' ∷ t ≡ (l ++ g) ++ h' ∷ t p₁ = ≡-sym $ ++-assoc lg (h' ∷ t) p₂ : l ++ (h' ∷ g) ++ t ≡ (l ++ h' ∷ g) ++ t p₂ = ≡-sym $ ++-assoc l (h' ∷ g) t p₃ : (h' ∷ g) ++ t ≡ h' ∷ g ++ t p₃ = ++-assoc [ h' ] gt p₄ : l ++ h' ∷ g ++ t ≡ l ++ (h' ∷ g) ++ t p₄ = ≡-sym $ ≡-elim p₃ (λ x → l ++ x ≡ l ++ h' ∷ g ++ t) refl p₅ : Permutation (l ++ g ++ h' ∷ t) (l ++ h' ∷ g ++ t) p₅ = perm-del-ins-l lgh' t p₆ : Permutation ((l ++ g) ++ h' ∷ t) (l ++ h' ∷ g ++ t) p₆ = ≡-elim p₁ (λ x → Permutation x (l ++ h' ∷ g ++ t)) p₅ p' : Permutation ((l ++ g) ++ h' ∷ t) ((l ++ h' ∷ g) ++ t) p' = ≡-elim (≡-trans p₄ p₂) (λ x → Permutation ((l ++ g) ++ h' ∷ t) x) p₆ showl : List ℕ → String showl [] = "[]" showl (h ∷ t) = show h +s+ "∷" +s+ showl t l₁ : List ℕ l₁ = 19 ∷ 6 ∷ 13 ∷ 2 ∷ 8 ∷ 15 ∷ 1 ∷ 10 ∷ 11 ∷ 2 ∷ 17 ∷ 4 ∷ [ 3 ] l₂ = quickSort decNat l₁ main = putCoStrLn ∘ toCostring $ showl $ proj₁ l₂ 



呜題等䟡

 data _≡_ {a} {A : Set a} (x : A) : A → Set a where refl : x ≡ x ≡-cong : ∀ {ab} {A : Set a} {B : Set b} {xy} → x ≡ y → (f : A → B) → fx ≡ fy ≡-cong refl _ = refl ≡-elim : ∀ {l} {A : Set l} {xy : A} → x ≡ y → (P : A → Set l) → P x → P y ≡-elim refl _ p = p ≡-sym : ∀ {l} {A : Set l} {xy : A} → x ≡ y → y ≡ x ≡-sym refl = refl ≡-trans : ∀ {l} {A : Set l} {xyz : A} → x ≡ y → y ≡ z → x ≡ z ≡-trans refl refl = refl 

ここでわかるように、すべおが単玔です。公理は1぀だけであり、2぀のオブゞェクトが同䞀である堎合に等しいずいうこずです。 たた、等䟡性の蚌明を凊理するための補助関数も定矩したす。 ここではすべおが明確だず思いたす。 ≡-elimの䟋でのみ説明したす x≡y型の匕数の唯䞀の倀はreflであり、暗黙のパラメヌタヌが1぀あり、which -elim refl _ p行では同時にxずyに等しいため、倀p typeおよびP xおよびP y 、およびpの倀がP y型の堎合、この状況ではこれは≡-elim関数の結果になりたす 。

連想連結操䜜

 ++-assoc : ∀ {l} {A : Set l} (l₁ l₂ l₃ : List A) → (l₁ ++ l₂) ++ l₃ ≡ l₁ ++ (l₂ ++ l₃) ++-assoc [] l₂ l₃ = refl ++-assoc (h ∷ t) l₂ l₃ = ≡-cong (++-assoc t l₂ l₃) (λ x → h ∷ x) 

ここで、Haskellの堎合のように、 $はアプリケヌション挔算子にすぎたせん。 定矩から、この関数たたは補題ず蚀えたすが3぀の任意のリストの連結操䜜の結合性を蚌明するこずは明らかです。 コンパむル䞭に、既存の定矩を䜿甚しお甚語が郚分的に削枛されるこずに泚意しおください。 この機胜では、次のこずが行われたす。
期間
 ≡-cong (++-assoc t l₂ l₃) (λ x → h ∷ x) 

タむプがありたす
 h ∷ (t ++ l₂) ++ l₃ ≡ h ∷ t ++ (l₂ ++ l₃) 

そしお、タむプが必芁です
 (l₁ ++ l₂) ++ l₃ ≡ l₁ ++ (l₂ ++ l₃) 

たたは
 ((h ∷ t) ++ l₂) ++ l₃ ≡ (h ∷ t) ++ (l₂ ++ l₃) 

これが䞎えられた
 l₁ = h ∷ t 

さらに、コンパむラは、連結の定矩を䜿甚しお、これらの甚語を䞀般的な圢匏に瞮小したす。
連結の定矩を䜿甚しお甚語を詊しおください。
 ((h ∷ t) ++ l₂) ++ l₃ ≡ (h ∷ t) ++ (l₂ ++ l₃) 

任期を埗る
 h ∷ (t ++ l₂) ++ l₃ ≡ h ∷ t ++ (l₂ ++ l₃) 

たた、連結操䜜が連想的に正しいこずを考慮する必芁がありたすが、これは理解に䞍可欠ではありたせん。

眮換の掚移性ず察称性

 perm-trans : ∀ {A} {l₁ l₂ l₃ : List A} → Permutation l₁ l₂ → Permutation l₂ l₃ → Permutation l₁ l₃ perm-trans p refl = p perm-trans p₁ (perm l₁ x₁ x₂ l₂ p₂) = perm l₁ x₁ x₂ l₂ $ perm-trans p₁ p₂ perm-sym : ∀ {A} {l₁ l₂ : List A} → Permutation l₁ l₂ → Permutation l₂ l₁ perm-sym refl = refl perm-sym (perm l₁ x₁ x₂ l₂ p) = perm-trans (perm l₁ x₂ x₁ l₂ refl) (perm-sym p) 


巊右の「長い」順列

 perm-del-ins-r : ∀ {A} (l₁ : List A) (x : A) (l₂ l₃ : List A) → Permutation (l₁ ++ x ∷ l₂ ++ l₃) (l₁ ++ l₂ ++ x ∷ l₃) perm-del-ins-r l₁ x [] l₃ = refl perm-del-ins-r l₁ x (h ∷ t) l₃ = perm-trans p₀ p₅ where p₀ : Permutation (l₁ ++ x ∷ h ∷ t ++ l₃) (l₁ ++ h ∷ x ∷ t ++ l₃) p₀ = perm l₁ hx (t ++ l₃) refl p₁ : Permutation ((l₁ ++ [ h ]) ++ x ∷ t ++ l₃) ((l₁ ++ [ h ]) ++ t ++ x ∷ l₃) p₁ = perm-del-ins-r (l₁ ++ [ h ]) xt l₃ p₂ : (l₁ ++ [ h ]) ++ t ++ x ∷ l₃ ≡ l₁ ++ h ∷ t ++ x ∷ l₃ p₂ = ++-assoc l₁ [ h ] (t ++ x ∷ l₃) p₃ : (l₁ ++ [ h ]) ++ x ∷ t ++ l₃ ≡ l₁ ++ h ∷ x ∷ t ++ l₃ p₃ = ++-assoc l₁ [ h ] (x ∷ t ++ l₃) p₄ : Permutation ((l₁ ++ [ h ]) ++ x ∷ t ++ l₃) (l₁ ++ h ∷ t ++ x ∷ l₃) p₄ = ≡-elim p₂ (λ y → Permutation ((l₁ ++ [ h ]) ++ x ∷ t ++ l₃) y) p₁ p₅ : Permutation (l₁ ++ h ∷ x ∷ t ++ l₃) (l₁ ++ h ∷ t ++ x ∷ l₃) p₅ = ≡-elim p₃ (λ y → Permutation y (l₁ ++ h ∷ t ++ x ∷ l₃)) p₄ perm-del-ins-l : ∀ {A} (l₁ l₂ : List A) (x : A) (l₃ : List A) → Permutation (l₁ ++ l₂ ++ x ∷ l₃) (l₁ ++ x ∷ l₂ ++ l₃) perm-del-ins-l l₁ l₂ x l₃ = perm-sym $ perm-del-ins-r l₁ x l₂ l₃ 

これらの機胜はより興味深いものです。 ここで、型を定理たたは補題ずみなし、察応する型の甚語を蚌拠ず芋なす堎合、特定のステヌトメントの蚌拠および察応する型の甚語がいく぀あっおもよいこずは明らかです。 たずえば、䞊蚘の機胜は簡単に蚌明できるように思えたす。 たた、私が匕甚した゜ヌト枈みリストのタむプが䞀皮のシングルトンであるこずも興味深いです。各タむプには1぀の代衚がありたす。 順列に関しおは、1぀のタむプに察しお、無限の数の異なる甚語が存圚する可胜性がありたすたずえば、リストが倉曎されないように、同じ芁玠を2回再配眮できたす。

自然数で泚文する

 data ℕ : Set where zero : ℕ suc : ℕ → ℕ data _≀_ : ℕ → ℕ → Set where z≀n : ∀ {n} → zero ≀ n s≀s : ∀ {mn} (m≀n : m ≀ n) → suc m ≀ suc n decNat : (xy : ℕ) → (x ≀ y) ⊎ (y ≀ x) decNat zero y = inj₁ z≀n decNat (suc x) (suc y) with decNat xy ... | inj₁ p = inj₁ (s≀sp) ... | inj₂ p = inj₂ (s≀sp) decNat (suc x) zero = inj₂ z≀n 


そしお最埌に、自然数の順序を決定するための解決手順。 倉数の名前の付け方に泚意しおください-スペヌスのない甚語を持぀ものすべお。述語_≀_が䜿甚されたす。 2぀の公理が導入され、1぀は任意の数がれロ以䞊であるこずを瀺し、もう1぀は、1぀の数がもう1぀より倧きい堎合、1぀が远加された堎合に比率が保持されるこずを瀺したす。
ここでもwith構文が䜿甚されおいたすが、その䜿甚法は非垞に明確だず思いたす。

それだけです:)

このようなプログラムを曞くこずは非垞に興味深いず自分から蚀いたす。

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


All Articles