-
Notifications
You must be signed in to change notification settings - Fork 246
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
RFC: changed _/_
and _%_
to use irrelevant instance arguments
#1538
Conversation
…rals and integers
I agree with the motivations and the overall design, my only question is
I seem to remember that we were not too keen on adopting more "exotic" Option 3 could be achieved by mixing the current approach with a record open import Agda.Builtin.Bool
open import Agda.Builtin.Nat
open import Agda.Builtin.Equality
open import Agda.Builtin.Unit
isSuc : Nat → Bool
isSuc (suc _) = true
isSuc _ = false
data ⊥ : Set where
isTrue : Bool → Set
isTrue true = ⊤
isTrue _ = ⊥
record NonZero (n : Nat) : Set where
field isNonZero : isTrue (isSuc n)
variable n : Nat
instance
nonZero : NonZero (suc n)
nonZero = record { isNonZero = tt }
f : {{NonZero n}} → ({{NonZero n}} → Nat) → Nat
f g = g
f' : {{NonZero (3 + n)}} → ({{NonZero (3 + n)}} → Nat) → Nat
f' g = g
f'' : ((n : Nat) -> {{NonZero n}} → Nat) → Nat
f'' g = g 2 Of course we would not have judgmental equality anymore but we |
Wait, I got confused by talks of "constructors" for |
Another benefit of defining the types for instance arguments locally is that it typically makes for much nicer error messages when instance search fails. |
@gallais So you're suggesting something like the following? private
NonZero' : ℕ → Set
NonZero' zero = ⊥
NonZero' (suc x) = ⊤
record NonZero (n : Nat) : Set where
field isNonZero : NonZero' n
instance
nonZero : NonZero (suc n)
nonZero = record { isNonZero = tt } I wonder if we can somehow avoid having the private definition... |
@gallais one advantage of using judgemental irrelevance that's just occurred to me is that instance search doesn't have to be unique for judgementally irrelevant arguments. For example we could define instances as follows: instance
gcd≢0ˡ : ∀ {m n} .{{_ : NonZero m}} → NonZero (gcd m n)
gcd≢0ˡ {m@(suc _)} {n} = ≢-nonZero (gcd[m,n]≢0 m n (inj₁ λ()))
gcd≢0ʳ : ∀ {m n} .{{_ : NonZero n}} → NonZero (gcd m n)
gcd≢0ʳ {m} {n@(suc _)} = ≢-nonZero (gcd[m,n]≢0 m n (inj₂ λ()))
lcm : ℕ → ℕ → ℕ
lcm zero n = zero
lcm m@(suc m-1) n = m * (n / gcd m n) This wouldn't work with your scheme right? |
We could stick to using
Correct. |
Alternatively we could just define the open import Agda.Builtin.Nat
data NonZero : Nat → Set where
suc : (n : Nat) → NonZero (suc n)
instance
nonZero : ∀ {n} → NonZero (suc n)
nonZero = suc _ |
@gallais 's "I agree with the motivations and the overall design, my only question is On the various alternatives presented here: I have a slight bias towards using well-debugged features, especially for something so close to the core of the library (as |
Hmm okay, so I've carried out several experiments and here are my thoughts:
So in summary, I think we should stick with the current simple definition of In my honest opinion, I would vote in favour of using it. As to whether people will be happy with judgemental irrelevance being used in the library, I only had a single query via the Agda mailing list on the proposed use of judgemental equality, and once the asker understood what it did they were fine with it being included. Furthermore, the people who tend to be very concerned with the exact base theory they are using (looking at Martín Escardó/Andy Pitts et al.) do not use the standard library anyway. Martín has recently being asking on Zulip for the ability to cut down the Agda base theory even further, which suggests that he's not even happy with default Agda. So the chances of even the existing standard library fulfilling his criteria are pretty slim I would guess. I guess the other argument is that we're the "standard" library and therefore using the features of "standard" Agda to improve the usability of the library should be fair game! What are people's thoughts? |
The argument "standard" Agda => "standard" library doesn't really move me: there are examples (even in Haskell) of standard features that end up not being used because they turn out to be a bad idea after all, even if they were loudly asked for. Having said that: I think this particular experiment is worth doing 'in production'. All the signs are that this is going to work and help. |
Okay, so it turns out a record-based definition does have one advantage. It means we don't have to have Therefore I've switched back to the record-based definition. |
Okay, I'm happy with this in it's current state. If no one comments by tomorrow, I'll merge it in and start working on extending it to the rationals. |
Can't believe how nicely this worked. No real hitches anywhere, all just sailed through. Definitely one of the most satisfying refactors I've done. As it's a proof of concept I've only done the refactoring for naturals and integers at the moment, with just the minimal necessary changes to the rational proofs. Those should massively simplify as well when we get round to it.
The one small design flaw exposed is that because the
NonZero
predicate ultimately falls back to the unit type, we have to importData.Unit
everywhere to get it to work. You can't seem to import instances publicly, so I think the best thing to do is actually to lift the predicates up to their own datatypes with the constructors declared as instances. That can be left for another time though.On the Agda side, I would also kind of like to have proper anonymous instance arguments so we can write
{{NonZero}}
instead of{{_ : NonZero}}
...