-
Notifications
You must be signed in to change notification settings - Fork 242
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
Add Data.Nat.Bounded
#2257
base: master
Are you sure you want to change the base?
Add Data.Nat.Bounded
#2257
Changes from 1 commit
85c485f
92fa7e9
f07cc16
dc8e53e
3d850f4
659d892
11bb699
51b6280
04fae4f
32eb86b
e560b6f
0fe029e
6052c4f
821f51c
194f122
9a734c1
dca2d54
823016b
623d854
4076cc5
f0f4883
e1214bd
10d4083
771b501
8d523c8
9b4ee0e
078d4f6
97f9cf9
eccf88d
f3e2550
383529a
3c3cbf3
ba4e922
00421a6
49430b3
594d35c
716d585
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,69 @@ | ||
------------------------------------------------------------------------ | ||
-- The Agda standard library | ||
-- | ||
-- Bounded natural numbers, and their equivalence to `Fin` | ||
------------------------------------------------------------------------ | ||
|
||
{-# OPTIONS --cubical-compatible --safe #-} | ||
|
||
module Data.Nat.Bounded where | ||
|
||
open import Data.Nat.Base as ℕ | ||
import Data.Nat.Properties as ℕ | ||
open import Data.Fin.Base as Fin using (Fin; zero; suc; toℕ) | ||
import Data.Fin.Properties as Fin | ||
open import Function.Base using (id; _∘_; _on_) | ||
open import Relation.Binary.Core using (_⇒_) | ||
open import Relation.Binary.PropositionalEquality.Core as ≡ using (_≡_; refl) | ||
open import Relation.Nullary.Decidable.Core using (recompute) | ||
open import Relation.Nullary.Negation.Core using (¬_) | ||
|
||
private | ||
variable | ||
m n : ℕ | ||
|
||
------------------------------------------------------------------------ | ||
-- Definition | ||
|
||
record BoundedNat (n : ℕ) : Set where | ||
constructor ⟦_⟧< | ||
field | ||
value : ℕ | ||
.{{bounded}} : value < n | ||
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. I don't think we very often have 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. Well, that had been my thinking underlying #1998 and (the reverted parts of) #2000 ... but indeed reimplementing this via 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. I like the idea of adding Supporting evidence: in code that Conor and I were playing around with, we had exactly 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. OK, so that's two of you... so either:
I guess it's the first choice, then, with the second as a possible downstream refactoring? DONE. 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. NB making 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. The addition of a Any comment on the trade-offs between the two, given that the latter is much more indirect than the former...? |
||
|
||
open BoundedNat public using () renaming (value to ⟦_⟧) | ||
|
||
-- Constructor | ||
|
||
⟦0⟧< : ∀ n → .{{ NonZero n }} → BoundedNat n | ||
⟦0⟧< (n@(suc _)) = ⟦ zero ⟧< where instance _ = z<s | ||
|
||
-- Destructors | ||
|
||
¬BoundedNat[0] : ¬ BoundedNat 0 | ||
¬BoundedNat[0] () | ||
|
||
isBounded : (i : BoundedNat n) → ⟦ i ⟧ < n | ||
isBounded (⟦ _ ⟧< {{bounded}}) = recompute (_ ℕ.<? _) bounded | ||
|
||
-- Equality on values is propositional equality | ||
|
||
bounded≡⇒⟦⟧≡⟦⟧ : _≡_ {A = BoundedNat n} ⇒ (_≡_ on ⟦_⟧) | ||
bounded≡⇒⟦⟧≡⟦⟧ = ≡.cong ⟦_⟧ | ||
|
||
⟦⟧≡⟦⟧⇒bounded≡ : (_≡_ on ⟦_⟧) ⇒ _≡_ {A = BoundedNat n} | ||
⟦⟧≡⟦⟧⇒bounded≡ refl = refl | ||
|
||
------------------------------------------------------------------------ | ||
-- Conversion to and from `Fin n` | ||
jamesmckinna marked this conversation as resolved.
Show resolved
Hide resolved
|
||
|
||
toFin : BoundedNat n → Fin n | ||
toFin ⟦ i ⟧< = fromℕ< i | ||
where -- a better version of `Data.Fin.Base.fromℕ<`? | ||
fromℕ< : ∀ m → .{{ m < n }} → Fin n | ||
fromℕ< {n = suc _} zero = zero | ||
fromℕ< {n = suc _} (suc m) {{m<n}} = suc (fromℕ< m {{s<s⁻¹ m<n}}) | ||
|
||
fromFin : Fin n → BoundedNat n | ||
fromFin i = ⟦ toℕ i ⟧< where instance _ = Fin.toℕ<n i | ||
|
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.
So to touch on your question of whether this belongs in the library or a readme file, I guess my question is what circumstances is this easier to work with than
Fin
? In general we try to avoid duplicate but equivalent definitions unless there is clear reason that sometimes one representation is easier to work with than the other...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.
Thanks, Matthew! I can think of two or three, some already in the initial preamble (which was really about helping someone solve a related problem of representation, where
Fin
didn't seem to fit well):Digit
bases for arithmetic, as a specialised instance/mode of use of the above;Data.Nat.DivMod
, to avoid the marshalling/unmarshalling required by the use ofFin
to ensure thatmod
is suitably bounded.Now, none of these could be said to be a deal-breaker, but I increasingly wonder whether
Fin
is better suited to its use as an indexing type (forVec
,List
, de Bruijn representations,Reflection
/deeply embedded syntaxes more generally, etc.), withℕ<
as an arithmetic type/Number
instance... cf. #2073 which I might now think makes the 'wrong' choice in usingFin
...Perhaps other pros (and cons!) might be lurking off-stage...
... UPDATED: (pro)
Data.Nat.DivMod.WithK
(no longer any need to consider erasing proofs of_≤″_
...?) and hence perhaps to the deprecation of_≤″_
altogether, cf. Remove (almost!) all external use of_≤″_
beyondData.Nat.*
#2262