-
Notifications
You must be signed in to change notification settings - Fork 272
Add Queue datatype #3084
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Draft
silas-hw
wants to merge
70
commits into
agda:master
Choose a base branch
from
silas-hw:queue
base: master
Could not load branches
Branch not found: {{ refName }}
Loading
Could not load tags
Nothing to show
Loading
Are you sure you want to change the base?
Some commits from the old base branch may be removed from the timeline,
and old review comments may become outdated.
Draft
Add Queue datatype #3084
Changes from all commits
Commits
Show all changes
70 commits
Select commit
Hold shift + click to select a range
4905cc6
Add definition of Queue and basic operations
silas-hw 4125b12
Add top-level Queue module
silas-hw bf7790b
Add some basic functions
silas-hw d26d47c
Add singleton function
silas-hw 6a8bf86
Fix imports
silas-hw 9056b95
Rename l : Level -> a : Level
silas-hw 85e54c5
Use two levels instead of one
silas-hw 95be562
Refactor Queue to use record definition
silas-hw bebe5a2
Refactor Queue to use record definition
silas-hw 9ef66fb
Cleanup
silas-hw a0b0353
Add properties file
silas-hw 253edac
Use record syntax in dequeue and enqueue
silas-hw 100d5db
Fix comment
silas-hw e3f8872
Fix typo in 'amortized'
silas-hw 48b6afd
Use as-pattern in enqueue
silas-hw 86bed0a
Merge branch 'queue' of https://github.com/silas-hw/agda-stdlib into …
silas-hw 0bf49e7
Use ⊥-elim on impossible dequeue case
silas-hw 0561f10
Update argument order for enqueue
silas-hw 1c1d2c6
Add proof that enqueue increases size by 1
silas-hw 55792de
Fix whitespaace
silas-hw 7e7edab
Fix whitespace
silas-hw 9810428
Reformat equaltiy proofs to abide by style guide
silas-hw bedd0df
Move TwoList Queue into its own module to allow for different impleme…
silas-hw 79b5d6c
Remove unneeded parens
silas-hw 5b36b00
Cleanup isEmpty
silas-hw 7de85c2
Rename 'list' to 'xs' in fromList
silas-hw 1c56ada
Make xs explicit in toList-fromList
silas-hw 5cacded
Use As-pattern in toList-fromList
silas-hw a3c6eda
Rename enqueueSuc to size-enqueue
silas-hw c3b93fb
Add start of QueueSpec
silas-hw 3c61400
Add size-empty lemma
silas-hw a2d5854
Add smart constructor
silas-hw 4ae85fc
fix: `whitespace` for `Data.Queue.TwoList.Properties`
jamesmckinna 257a08b
Update src/Data/Queue/QueueSpec.agda
silas-hw 612c743
Update src/Data/Queue/QueueSpec.agda
silas-hw e0b83dd
Improve null-::
silas-hw a071100
Add RawQueue interface and bundle into IsQueue
silas-hw 379375a
Cleanup code
silas-hw d724dfb
Define equality relation on TwoList queues
silas-hw 41e76dd
Add approx relation
silas-hw c2246b4
Remove stale file
silas-hw e8ff3b8
Fix whitespace
silas-hw e2cc2c8
Cleanup dequeue on TwoList
silas-hw e790193
Add properties to IsQueue
silas-hw 6a717da
Fix Properties to use new definitions in QueueSpec
silas-hw d1a9ea9
Prove IsEquivalence of ≈
silas-hw 2ec3eaa
fix: `whitespace`
jamesmckinna 99fc8f1
Cleanup code
silas-hw 6fe776f
Add All< and Null<
silas-hw 0512a11
Update TwoList Queue to use SnocList
silas-hw 009697c
Fix whitespace
silas-hw b4e1ec7
Cleanup code
silas-hw 07212a4
Fix whitespace
silas-hw 84d517b
Prove ≈-resp-Empty on TwoList
silas-hw 26556d9
Prove empty-toList on TwoList
silas-hw 200a1fe
Rename and move lemmas to appropriate places
silas-hw 501ef41
Move RawQueue instance of TwoList to Instances module
silas-hw 46301be
Replace ⊥-elim with contradiction
silas-hw 759d398
Move more properties out of TwoList.Base
silas-hw 18d7fec
Change order that toList and fromList should assume
silas-hw ce07bd4
Prove toList-enqueue
silas-hw 045b5d0
Fix queue smart constructor
silas-hw 413a77d
Add proof of empty-fromList for TwoList
silas-hw 2a4b922
Add proof of fromList-toList for TwoList
silas-hw e663f52
Update type of dequeue
silas-hw f3dc094
Fix remaining hole
silas-hw 6b34f14
Remove goal
silas-hw 56222e5
Add ++-identity proofs
silas-hw 32b71f8
Prove more properties of TwoList queue
silas-hw 418e2fe
Use cong! tactic where possible
silas-hw File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,11 @@ | ||
| ------------------------------------------------------------------------ | ||
| -- The Agda standard library | ||
| -- | ||
| -- Queues | ||
| ------------------------------------------------------------------------ | ||
|
|
||
| {-# OPTIONS --without-K --safe #-} | ||
|
|
||
| module Data.Queue where | ||
|
|
||
| open import Data.Queue.TwoList.Base public | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,82 @@ | ||
| ------------------------------------------------------------------------ | ||
| -- The Agda standard library | ||
| -- | ||
| -- Queue specification | ||
| ------------------------------------------------------------------------ | ||
|
|
||
| {-# OPTIONS --without-K --safe #-} | ||
|
|
||
| module Data.Queue.QueueSpec where | ||
|
|
||
| open import Data.Bool.Base using (Bool) | ||
| open import Data.List.Base as List using (List; []; length; _∷_) | ||
| open import Data.List.Relation.Unary.All using (Null) | ||
| open import Data.Maybe.Base using (Maybe; nothing; just) | ||
| open import Data.Nat.Base using (ℕ) | ||
| open import Data.Product.Base using (_×_; proj₁; proj₂) | ||
| open import Function.Base using (_∘_) | ||
| open import Level | ||
| open import Relation.Binary.Core using (Rel; _=[_]⇒_) | ||
| open import Relation.Binary.Definitions using (_Respects_) | ||
| open import Relation.Binary.Structures using (IsEquivalence) | ||
| open import Relation.Binary.PropositionalEquality.Core using (_≡_) | ||
| open import Relation.Nullary.Decidable.Core using (yes; no; isYes; False; does) | ||
| open import Relation.Unary using (Pred; Decidable) | ||
|
|
||
| private | ||
| variable | ||
| a b : Level | ||
| A : Set a | ||
| B : Set b | ||
|
|
||
| -- RawQueue defines the 'computations' available on Queues | ||
| -- without any of the associated proofs that determine its | ||
| -- correctness. | ||
| record RawQueue (Q : Set a → Set a) : Set (suc a) where | ||
|
|
||
| field | ||
| _≈_ : ∀ {A : Set a} → Rel (Q A) a | ||
| Empty : ∀ {A : Set a} → Pred (Q A) a | ||
| empty? : Decidable (Empty {A = A}) | ||
| fromList : List A → Q A | ||
| toList : Q A → List A | ||
| enqueue : A → Q A → Q A | ||
| dequeue : (q : Q A) → .{{False (empty? q)}} → Q A × A | ||
| size : Q A → ℕ | ||
|
|
||
| empty : Q A | ||
| empty = fromList [] | ||
|
|
||
| pure : A → Q A | ||
| pure = fromList ∘ List.[_] | ||
|
|
||
| to𝔹 : Q A → Bool | ||
| to𝔹 = isYes ∘ empty? | ||
|
Comment on lines
+53
to
+54
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Similarly, should this be called |
||
|
|
||
| dequeue′ : Q A → Maybe (Q A × A) | ||
| dequeue′ q with empty? q in eq | ||
| ... | yes _ = nothing | ||
| ... | no _ = just (dequeue q) | ||
| where instance | ||
| _ : False (empty? q) | ||
| _ rewrite eq = _ | ||
|
|
||
| -- IsQueue bundles RawQueue with proofs of a Queues correctness, | ||
| -- such as enqueue adding 1 to the Queue's size | ||
| -- NOTE: not finished adding everything! | ||
| record IsQueue {Q : Set a → Set a} (rawQ : RawQueue Q) : Set (suc a) where | ||
|
|
||
| open RawQueue rawQ | ||
|
|
||
| field | ||
| isEquivalence : IsEquivalence (_≈_ {A = A}) | ||
| ≈-resp-Empty : Empty Respects (_≈_ {A = A}) | ||
| ≈-=[toList]⇒-≡ : (_≈_ {A = A}) =[ toList ]⇒ _≡_ | ||
| empty-toList : ∀ {q : Q A} → Empty q → Null (toList q) | ||
| empty-fromList : ∀ {xs : List A} → Null {A = A} xs → Empty (fromList xs) | ||
| toList-fromList : ∀ {q : Q A} {xs : List A} → q ≈ fromList xs → toList q ≡ xs | ||
| fromList-toList : ∀ {q : Q A} {xs : List A} → xs ≡ toList q → fromList xs ≈ q | ||
| toList-enqueue : ∀ {q : Q A} {x : A} → toList (enqueue x q) ≡ x ∷ toList q | ||
| -- for some reason, let x , r = ... doesn't bind x and r?? | ||
| toList-dequeue : ∀ {q : Q A} → .{{i : False (empty? q)}} → | ||
| let xr = dequeue q {{i}} in toList q ≡ toList (proj₁ xr) List.∷ʳ proj₂ xr | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,129 @@ | ||
| ------------------------------------------------------------------------ | ||
| -- The Agda standard library | ||
| -- | ||
| -- Queues, basic types and operations | ||
| ------------------------------------------------------------------------ | ||
| {-# OPTIONS --without-K --safe #-} | ||
|
|
||
| -- Queues implemented with the two-list method described in | ||
| -- "Purely Functional Data Structures", Chris Okasaki, 1996 | ||
| -- | ||
| -- Note that the weaker invariant is used here that only guarantees | ||
| -- amortized O(1) when the structure is used non-persistently. | ||
|
|
||
| module Data.Queue.TwoList.Base where | ||
|
|
||
| open import Level using (Level) | ||
| open import Data.Bool.Base using (Bool; true; false) | ||
| open import Data.List.Base as List using (List; []; _∷_; reverse; _++_; length; null) | ||
| open import Data.List.Relation.Unary.All using (Null; []; _∷_) | ||
| open import Data.List.Relation.Unary.All.Properties using (null⇒Null; Null⇒null) | ||
| open import Data.Maybe.Base using (Maybe; nothing; just) | ||
| open import Data.Nat.Base using (ℕ; zero; suc; _+_) | ||
| open import Data.Product using (_×_; _,_; proj₂) | ||
| open import Data.Queue.QueueSpec using (RawQueue; IsQueue) | ||
| open import Data.SnocList.Base as SnocList using (List<; toList>; fromList>; []; _<:_; _<><_) | ||
| open import Data.SnocList.Relation.Unary.All | ||
| open import Data.SnocList.Relation.Unary.All.Properties using (¬null-<:; null-<:→nullxs) | ||
| open import Data.Unit.Base using (⊤) | ||
| open import Function.Base using (id; const; _∘_) | ||
| open import Relation.Binary.PropositionalEquality.Core using (_≡_) | ||
| open import Relation.Binary.Core using (Rel) | ||
| open import Relation.Nullary using (¬_) | ||
| open import Relation.Nullary.Negation using (contradiction) | ||
| open import Relation.Nullary.Decidable.Core using (yes; no; isYes; False) | ||
| open import Relation.Nullary.Reflects using (ofʸ; ofⁿ) | ||
| open import Relation.Unary using (Pred; Decidable) | ||
|
|
||
| private | ||
| variable | ||
| a b : Level | ||
| A : Set a | ||
| B : Set b | ||
|
|
||
| -- A Queue consists of a front (dequeue) and back (enqueue) list | ||
| -- When enqueing (unless it is the first element), elements are cons'd | ||
| -- to the enqueue list. | ||
| -- | ||
| -- When dequeuing, elements are taken from the head of the dequeue | ||
| -- list. If this is empty, the enqueue list is reversed and swapped | ||
| -- with the dequeue list. | ||
| -- | ||
| -- The dequeue-list should be empty iff the whole queue is empty. | ||
|
|
||
| record Queue (A : Set a) : Set a where | ||
| constructor mkQ | ||
| field | ||
| front : List< A | ||
| back : List A | ||
|
silas-hw marked this conversation as resolved.
|
||
| inv : Null< front → Null back | ||
|
|
||
| ------------------------------------------------------------------------ | ||
| --- Basic Functions/Relations/Operators | ||
|
|
||
| Empty : ∀ {A : Set a} → Pred (Queue A) a | ||
| Empty {a} {A} q = Null< (Queue.front q) | ||
|
|
||
| empty? : Decidable (Empty {A = A}) | ||
| empty? (mkQ front back inv) .Relation.Nullary.does = SnocList.null front | ||
| empty? (mkQ [] back inv) .Relation.Nullary.proof = ofʸ [] | ||
| empty? (mkQ (xs <: x) back inv) .Relation.Nullary.proof = ofⁿ λ null< → contradiction null< ¬null-<: | ||
|
|
||
| isEmpty : Queue A → Bool | ||
| isEmpty q = SnocList.null (Queue.front q) | ||
|
|
||
| ------------------------------------------------------------------------ | ||
| --- Smart Constructor | ||
|
|
||
| queue : List< A → List A → Queue A | ||
| queue [] ys = mkQ ([] <>< ys) [] (const []) | ||
| queue xs@(_ <: _) ys = mkQ xs ys null-<:→nullxs | ||
|
|
||
| ------------------------------------------------------------------------ | ||
| --- Conversion to/from List | ||
|
|
||
| -- Create a List from a Queue, such that the last that would be dequeued | ||
| -- becomes the head of the list | ||
| toList : Queue A → List A | ||
| toList q = (Queue.back q) ++ (toList> (Queue.front q)) | ||
|
|
||
| -- Create a Queue from a List, such that the elements | ||
|
Collaborator
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Probably consider |
||
| -- of the list would be dequeued starting from its last element | ||
| fromList : List A → Queue A | ||
| fromList xs = queue [] xs | ||
|
|
||
| ------------------------------------------------------------------------ | ||
| -- Construction & Destruction | ||
|
|
||
| empty : Queue A | ||
| empty = fromList [] | ||
|
|
||
| enqueue : A → Queue A → Queue A | ||
| enqueue x q with bs ← Queue.back q | Queue.front q | ||
| ... | [] = queue ([] <: x) [] | ||
| ... | front@(_ <: _) = queue front (x ∷ bs) | ||
|
|
||
| dequeue : ∀ (q : Queue A) .{{_ : False (empty? q)}} → Queue A × A | ||
| dequeue (mkQ (xs <: x) back _) = queue xs back , x | ||
|
|
||
| -- Create a queue with a single element | ||
| singleton : A → Queue A | ||
| singleton = fromList ∘ List.[_] | ||
|
|
||
| -- map : (A → B) → Queue A → Queue B | ||
| -- map f empty = empty | ||
| -- map f (queue x xs ys) = queue (f x) (List.map f xs) (List.map f ys) | ||
|
|
||
| ------------------------------------------------------------------------ | ||
| -- Relations | ||
|
|
||
| -- Under the property that toList returns a list in | ||
| -- the order of dequeue | ||
| _≈_ : ∀ {A : Set a} → Rel (Queue A) a | ||
| q ≈ q' = (toList q) ≡ (toList q') | ||
|
jamesmckinna marked this conversation as resolved.
|
||
|
|
||
| ------------------------------------------------------------------------ | ||
| -- Size | ||
|
|
||
| size : Queue A → ℕ | ||
| size = length ∘ toList | ||
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,56 @@ | ||
| ------------------------------------------------------------------------ | ||
| -- The Agda standard library | ||
| -- | ||
| -- Instances of TwoLisQueue | ||
| ------------------------------------------------------------------------ | ||
|
|
||
| {-# OPTIONS --without-K --safe #-} | ||
|
|
||
| module Data.Queue.TwoList.Instances where | ||
|
|
||
| open import Data.Queue.TwoList.Base | ||
| open import Data.Queue.TwoList.Properties | ||
| open import Data.Queue.QueueSpec using (RawQueue; IsQueue) | ||
| open import Level using (Level) | ||
|
|
||
| private | ||
| variable | ||
| a b : Level | ||
| A : Set a | ||
| B : Set b | ||
|
|
||
| ------------------------------------------------------------------------ | ||
| --- TwoList Queue is a Raw Queue | ||
|
|
||
| instance | ||
| TwoList-RawQueue : RawQueue {a} Queue | ||
| TwoList-RawQueue = record | ||
| { _≈_ = _≈_ | ||
| ; Empty = Empty | ||
| ; empty? = empty? | ||
| ; fromList = fromList | ||
| ; toList = toList | ||
| ; enqueue = enqueue | ||
| ; dequeue = dequeue | ||
| ; size = size | ||
| } | ||
|
|
||
| ------------------------------------------------------------------------ | ||
| -- TwoList Queue is a Queue! | ||
|
|
||
| -- for some reason, unless manually passing some implicits, other implicits remain | ||
| -- unsolved? This is also means that you can't assign fields with record syntax and | ||
| -- have to use co-pattern matching. My knowledge of implicits isn't good enough to know | ||
| -- why or if this indicates 'bad ergonomics' | ||
|
|
||
| instance | ||
| TwoList-IsQueue : IsQueue {a} TwoList-RawQueue | ||
| TwoList-IsQueue .IsQueue.isEquivalence = ≈-isEquivalence | ||
| TwoList-IsQueue .IsQueue.≈-resp-Empty {x = x} {y} = ≈-resp-Empty {x = x} {y = y} | ||
| TwoList-IsQueue .IsQueue.≈-=[toList]⇒-≡ {x = x} {y} = ≈-=[toList]⇒-≡ {x = x} {y = y} | ||
| TwoList-IsQueue .IsQueue.empty-toList {q = q} = empty-toList {q = q} | ||
| TwoList-IsQueue .IsQueue.empty-fromList = empty-fromList | ||
| TwoList-IsQueue .IsQueue.toList-fromList {q = q} = toList-fromList {q = q} | ||
| TwoList-IsQueue .IsQueue.fromList-toList {q = q} = fromList-toList {q = q} | ||
| TwoList-IsQueue .IsQueue.toList-enqueue {q = q} = toList-enqueue {q = q} | ||
| TwoList-IsQueue .IsQueue.toList-dequeue {q = q} = toList-dequeue {q = q} |
Oops, something went wrong.
Oops, something went wrong.
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe this should itself be
Data.Queue.TwoListas the top-level (sic) module for this implementation?Again, up for discussion!
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
As in have a file
Data/Queue/TwoList.agdawith this content?Indeed, this file itself will be changed to not just have
TwoList.Baseimported, and will then likely importData,Queue.TwoListinstead?