Add Queue datatype - #3084
Conversation
|
When adding new functionality, we tend to make somewhat larger PRs than when fixing things. In particular, a bunch of properties should be proved too. The main reason is that quite often the proofs reveal when some of functionality was written in a correct-but-hard-to-use (or reason about) manner. So basically all of #3083 will need to be done in this PR. On the other hand, asking for reviews of the intermediate steps is a good idea. |
| toList empty = [] | ||
| toList (queue dq-hd dq-tail eq) = dq-hd ∷ (dq-tail ++ (reverse eq)) | ||
|
|
||
| -- Create a Queue from a List, such that the elements |
There was a problem hiding this comment.
Probably consider fromSnocList too.
There was a problem hiding this comment.
Some alternative suggestions as to implementation.
Against @JacquesCarette , and because I'm a bit more 'OO-minded', I tend to put things like Empty/isEmpty as manifest fields of the record, because then I don't have to think about the scope management. Similarly toList, because all the pieces are at-hand without further ado... but YMMV.
As for references for this kind of implementation, probably Okasaki's "Purely functional data structures" would be the go-to citation?
Oh, and: fix-whitespace!
There is also https://doi.org/10.1017/S0956796800001489 |
So, eg.: toList-fromList : toList (fromList xs) ≡ xsThe converse direction requires some simulation relation on |
Co-authored-by: jamesmckinna <31931406+jamesmckinna@users.noreply.github.com>
Co-authored-by: jamesmckinna <31931406+jamesmckinna@users.noreply.github.com>
|
hmmm... circular dependencies? Does splitting the |
|
I think it would rather be splitting Or maybe moving the definitions used in the instance of |
…3091) * [ add ] more properties of `Data.List.Relation.Unary.All.Null` * streamline case analysis * fix: regularise `null-∷` to use `¬_` * fix: capitalisation * fix: capitalisation
| nullxs→xs≡[] : Null xs → xs ≡ [] | ||
| nullxs→xs≡[] [] = refl | ||
|
|
||
| xs≡[]→nullxs : xs ≡ [] → Null xs | ||
| xs≡[]→nullxs xs≡[] rewrite xs≡[] = [] | ||
|
|
There was a problem hiding this comment.
Can these be refactored to make use of the lemmas added in #3091
| _ : False (empty? q) | ||
| _ rewrite eq = _ | ||
|
|
||
| -- IsQueue bundles RawQueue with proofs of a Queues correctness, |
There was a problem hiding this comment.
The operative word here is 'bundle'.
I think that IsQueue, even if only for consistency with existing distinctions between 'structure' and 'bundle' (eg. see #3052), should be considered as a structure, and thus parametrised on Q and the rawQ : RawQueue Q .
A bundled Queue would then be a record with three fields:
- the type constructor
Q - its associated
rawQ - the proof that it, indeed, satisfies
IsQueue
Cf. #2252
There was a problem hiding this comment.
Oh, and a propos @JacquesCarette 's jeremiad in #3052 we should perhaps consider instead write QueueSig rather than RawQueue...?
There was a problem hiding this comment.
I see! And from the perspective of a relatively new developer, XSig is more immediately obvious than RawQueue, so I'm in favor of that
There was a problem hiding this comment.
And for the bundle, how about 'lifting' the Sig functions to be on the bundle itself?, e.g.
record Queue (A : Set a) : Set (suc a) where
field
Q : Set a → Set a
q : Q A
rawQueue : RawQueue A Q
isQueue : IsQueue A rawQueue
open Queue
-- 'lifted' functions
enqueue : {a : Level} → {A : Set a} → A → Queue A → Queue A
enqueue x q' = record { Q = q' .Q ; q = RawQueue.enqueue (q' .rawQueue) x (q' .q) ; rawQueue = q' .rawQueue ; isQueue = q' .isQueue }Is there some nice automatic way of doing this?
There was a problem hiding this comment.
Ooh. Maybe I was too hasty/casual in my suggestion above regarding the bundle (I think the structure story makes sense)...
Is it obviously a good idea to allow the basic operations potentially to change the underlying type constructor Q upon each invocation? (your suggested lifted versions obviously do not, but it isn't ruled out for the implied API defined by the bundled version?)
Perhaps some more thought required?
Will eventually resolve #3083. Uses the two-list method mentioned in #3072 (but in a PR not generated by an LLM this time).
There may be some poor stylistic choices due to my unfamiliarity with the standard library, for which I am sorry! There are some 'low hanging' basic operations that could still be added, but I think those would be good for separate PRs.