-
Notifications
You must be signed in to change notification settings - Fork 247
Add redundant fields to algebraic structures to make diamonds commute #985
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
Conversation
I think this is the right hierarchy. That being said, I have found that it does not necessarily play nice with instance search if that would ever become default for the std lib. The issue there is (I think) that it is not possible to mark the |
FWIW, that is probably not a problem specific to this PR, but might equally apply to the current hierarchy. But if we're going to make breaking changes, it might be worth considering instance search, which has become more reliable now that it doesn't do backtracking by default. |
This is something I don't know much about and haven't thought about at all. Are there the same problems with instance search for |
I haven't tried changing the definitions to support instance search, but I would be extremely surprised if the current definitions work well out of the box. A similar diamond in a different setting which does use instance search gave me quite a few headaches. |
Do you have a (non-)working example? I feel that I half-understand what the problems might be, but can't put them together to see what goes wrong. How would any diamonds be handled by instance search, for example? |
I started trying it out with the stdlib's definitions but ran into too many name clashes to quickly produce an example. What I'm trying to say is: if the std library intends to start making use of instance search more, we should expect breaking changes to the algebra hierarchy. Since this PR also proposes breaking changes (for the better), we should consider combining both and not bother people twice :) If instance search for the std lib is not on the agenda, then my concerns are a non-issue. |
Thanks @laMudri, this looks pretty good. I have a couple of comments though: I'd ideally like to keep the left and right biased versions very minimal to discourage their use as much as possible, i.e. just record IsCommutativeMonoidˡ (∙ : Op₂ A) (ε : A) : Set (a ⊔ ℓ) where
field
isSemigroup : IsSemigroup ∙
identityˡ : LeftIdentity ε ∙
comm : Commutative ∙ we could then have a function I'm also thinking that maybe we should have them in a different module, maybe Finally
It's definitely on a lot of people's agenda: about every 6 months or so we have someone keen to improve the standard library's support for instance search. The problem is that no-one as of yet has come up with concrete proposals about what to include and how to organise it. We're definitely open to any suggestions for the design though 👍 |
Would we need the left/right biased structures at all if Agda had default field implementations like Haskell? |
I'm developing a hierarchy of partial algebras (e.g., IsPartialCommutativeMonoid <: IsPartialMonoid <: IsPartialSemigroup) where the binary operation is represented by a partial, non-functional ternary relation in Agda. The setup is pretty close to what is in this PR, but uses instance search. I'll be releasing it soonish as an artifact for a CPP '20 paper. It could probably serve as a first design draft for the use of instances in the standard library. |
I see
Yeah, I could get behind this.
I quite like the trick of this function being a member of
Also agreed. It's a good property that these definitions play no role in the algebra hierarchy, and we can signal that by putting them somewhere else, where they're not depended on. Maybe we could find a nicer name. Somehow these definitions should only be used transiently, but they shouldn't be totally discouraged.
Could this be done in a separate PR? IIRC, this is an orthogonal issue. |
Ah, I guess you have this in mind: -- Note that `IsLattice` is not defined in terms of `IsSemilattice`
-- because the idempotence laws of ∨ and ∧ can be derived from the
-- absorption laws, which makes the corresponding "idem" fields
-- redundant. The derived idempotence laws are stated and proved in
-- `Algebra.Properties.Lattice` along with the fact that every lattice
-- consists of two semilattices. Then yes, this PR is a decent place to go against this comment. But then we have the concerns from #676. Did we come to any kind of consensus? It seems clear than both the algebraic and the order theoretic views of lattices are valid, in a way that |
Sorry that it took a while for me to comment on this - too many deadlines, and as this is an issue I care about a lot, it needs a decent block of time to respond properly. The foundational inspiration of this PR, namely
and
are spot on. However, you happened to notice a particular diamond that was a problem, whereas in a fuller Algebra hierarchy, there are hundreds of them. In my old prototype , there is an Algebra library with 512 diamonds in it. Closer to Agda proper, we have an eslip prototype that does meta-programming to generate the kinds of things you are currently doing by hand (i.e. it generates Agda that typechecks). Its library (I don't have the link handy) has about 300 algebraic structures in it. The theory behind that is described in a submitted journal paper. Of course, none of that is ready for prime time, yet. Though I think useful background material. On the details of what you're doing here: first, you should note that this left/right diamond you've encountered really belongs as Roughly speaking, any rigid record 'hierarchy' is going to fail -- there are simply way too many diamonds to hope to "get it right". Having said that, because there is no alternative suggestion at hand, it is worthwhile evaluating what you propose here "on its own merits", to see if it is a step forward. Yes, I do think this is an improvement. [And that the improvements that one can make to |
While I was writing the above, once more comment came in. The issue around Furthermore, the additional comments (about redundancy of fields) shows that, in even for things that end up being equivalent, what fields have to be primitive, and which can be derived, is very (very!) tricky. The issues, unlike above, are no longer structural: the 'theory presentation morphisms' involved are not embeddings, they are full views. When you have views in both directions, this is a situation where Realms are a useful idea (if it was actually implemented...). Yes, in HoTT, this is regarded as "free", if you're a theoretician who doesn't care about computational matters (HoTT people will, when pressed, admit that 'transport' can indeed involved arbitrary computations). I am adverse to hiding arbitrary computations, so I prefer to make those kinds of 'coercions' explicit. That's all a long winded way to say that the isomorphism between |
To pick off stuff I can respond to quickly:
Do you have a simple example? This seems believable, but an example would serve as good motivation and make sure everyone is on the same page. I can imagine things getting difficult like this if you start mixing algebra and order (so that all operators are monotonic, have some properties, and you can also separately take meets/joins).
There is a middle ground. In particular, it's possible to have record IdempotentCommutativeMonoid c ℓ : Set (suc (c ⊔ ℓ)) where
infixl 7 _∙_
infix 4 _≈_
field
Carrier : Set c
_≈_ : Rel Carrier ℓ
_∙_ : Op₂ Carrier
ε : Carrier
isIdempotentCommutativeMonoid : IsIdempotentCommutativeMonoid _≈_ _∙_ ε
open IsIdempotentCommutativeMonoid isIdempotentCommutativeMonoid public
commutativeMonoid : CommutativeMonoid _ _
commutativeMonoid = record { isCommutativeMonoid = isCommutativeMonoid }
open CommutativeMonoid commutativeMonoid public
using (rawMagma; magma; semigroup; rawMonoid; monoid)
BoundedMeetSemilattice = IdempotentCommutativeMonoid
module BoundedMeetSemilattice {c ℓ} (idemCommMonoid : IdempotentCommutativeMonoid c ℓ) where
open IdempotentCommutativeMonoid idemCommMonoid public
renaming (ε to ⊤; _∙_ to _∧_; et cetera...) Alternatively, they could share content in When they are incorporated into |
In some ways, one can claim that right above More convincing is the full 4D cube sitting in modal logics around S3 -- see about 40% of the way down on Halleck's list of modal logics page. Note that that link is to a mirror, as the 'main' page seems down right now. It gets weird when you mix in order. There are valid structures that are monotonic for some operations but not all - sorry, I don't remember which ones. So the mockup you give gives a |
To bring this back to the issue at hand, it seems that both of the prototype libraries don't try to address redundancy of axioms in the presence of more structure, which is what is causing the complexity here. Yes, the inheritance hierarchy could be better with some more technology, but this only helps when giving instances and adding to the hierarchy. When using structures, we can just open everything, and the difference between fields and fields of fields, and even defined records made up only of fields, goes away. What this pull request does is to ensure that fields don't turn into complex auxiliary definitions, which does matter in usage sometimes. I think the best course of action at the moment is to define the scope of this PR, and then press on. From a quick look through, it seems that we have the following modules that may need changing if we decide that the changes here are good:
This is just all of the
I think each of the 2 or 3 modules that need work, plus the things about algebraic lattices, would fit into their own pull requests. As such, I'll start work on making the library typecheck after the changes I've made so far, and see how it goes. I still consider this pull request an experiment, so I'd like to see this sample through. |
I think your assessment makes a lot of sense, as does your plan. |
That's the library checking again. There aren't really too many changes needed, so that's a good thing. I've tended to use the biased structures only when the properties they derive aren't already proven. In fact, I've only used biased structures in The most work per instance seemed to be caused by |
The changes are quite modest and straightforward - I agree that's a good sign. Many are indeed improvements. BTW, it seems odd to me that semiring is commutative by default. |
There must be some misunderstanding here. stdlib has both |
I think it was my misunderstanding of your statement
I guess you meant |
What I meant to say here is that |
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.
Looks good. A couple more comments.
Oh and we need a changelog entry explaining the changes. |
Thanks for all the comments today. I'll probably go through them seriously tomorrow, as well as having a look at some of the other areas I identified in this thread a few comments back. It just works out that this timing has worked out well for me. 🙂 |
6b59a40
to
228b261
Compare
Okay, looks like this has settled down. I'll merge it in tomorrow unless anyone has any more comments? |
This pull request is an experiment in doing what I suggested in #898. The guiding principle is that when giving an instance of a subclass, all of the fields of its superclasses should be accessible. This is currently violated in, for example,
CommutativeMonoid
. The supporting definitionIsCommutativeMonoid
is currently the following.It violates the stated principle because it is impossible to give a specific proof of
identityʳ
. Instead, we must accept the proof ofidentityʳ
that goes viaidentityˡ
andcomm
.Problems with the current definition come about under these circumstances:
The outcome is that it gets difficult to parametrise over algebraic structures, as one would like to do for modules over a ring, for example (#897).
The particular diamond in the case of
CommutativeMonoid
isIsAbelianGroup
happens to be defined with anIsGroup
field, meaning that it does have anidentityʳ
field. This, therefore, is thrown away by the embedding intoCommutativeMonoid
, and gets reconstructed in the embedding ofCommutativeMonoid
intoMonoid
. Thus, this diamond does not commute definitionally.In this pull request,
IsCommutativeMonoid
has the following definition.Additionally, for convenience and some level of compatibility, there are new definitions
IsCommutativeMonoidˡ
andIsCommutativeMonoidʳ
, with the former defined as follows. Having both of these definitions means that we're no longer biased towards theidentityˡ
law – we could give only theidentityʳ
law (viaIsCommutativeMonoidʳ
) instead.The intended method of using this structure looks something like the following.
These structures do not get their own bundles, as they shouldn't be used for any purpose other than the last example.
This branch will currently not build, as I haven't inserted the coercions throughout the library. A quick grep suggests that there are 20
CommutativeMonoid
instances to fix, plus (probably fewer) instances ofCommutativeSemiring
andRing
. I want to get most of the design done before making lots of changes throughout the library.