Skip to content
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

[DRY] what's the best way to publicly re-export properties/structure? #2391

Open
jamesmckinna opened this issue May 20, 2024 · 6 comments
Open

Comments

@jamesmckinna
Copy link
Contributor

jamesmckinna commented May 20, 2024

Cf. #2255 of which this is somehow a generalisation ...

Thanks to the sophistication of the re-exporting strategies embodied in Relation.Binary.Bundles, we could streamline concrete instances of such strategies, such as in Data.List.Binary.Relation.Equality.DecSetoid.

Compare the following (23 LOC; 3 imports; 1 explicit definition; and 2 public re-exports, the first of which also introduces the correct fixity, the second shared with the existing version): UPDATED in the light of errors caught by #2490 ;-)

open import Relation.Binary.Bundles using (DecSetoid)

module Data.List.Relation.Binary.Equality.DecSetoid
  {a ℓ} (DS : DecSetoid a ℓ) where

import Data.List.Relation.Binary.Equality.Setoid as SetoidEquality
open import Data.List.Relation.Binary.Pointwise using (decSetoid)
open DecSetoid DS using (setoid)

------------------------------------------------------------------------
-- Additional properties

≋-decSetoid : DecSetoid _ _
≋-decSetoid = decSetoid DS

open DecSetoid ≋-decSetoid public
  using ()
  renaming (isDecEquivalence to ≋-isDecEquivalence; _≟_ to _≋?_)

------------------------------------------------------------------------
-- Make all definitions from setoid equality available

open SetoidEquality setoid public

with the existing version (31 LOC; 7 imports; 3 explicit definitions, incl. the fixity declaration; and the 1 public re-export shared with the above).

So we trade economy of expression/export for explicitness of definition... although in each case, such definitions are largely by delegation, so it's not immediately clear that there is much gain in understanding, except the documentation afforded by the types...

Which is 'better'/preferable, and which style should the library adopt from v2.* onwards?

@jamesmckinna
Copy link
Contributor Author

jamesmckinna commented May 20, 2024

Similarly, existing style seems to be to build up, definition-by-definition, towards eg Setoid instances, as in eg. Data.List.Binary.Relation.Equality.Setoid, rather than define the Setoid first, and then open it publicly and suitably renaming its components... as:

------------------------------------------------------------------------
-- Relational properties
------------------------------------------------------------------------

≋-setoid : Setoid _ _
≋-setoid = PW.setoid S

open Setoid ≋-setoid public
  using ()
  renaming (refl to ≋-refl; reflexive to ≋-reflexive; sym to ≋-sym; trans to ≋-trans; isEquivalence to ≋-isEquivalence)

@jamesmckinna
Copy link
Contributor Author

Cf. For contrast/illustration of the status quo, my earlier comments on #2382 (and @Taneb 's recent review of #2393 ), the refinement of the above heuristic would be to emphasise *re-*export of bundles/structures...

@MatthewDaggitt
Copy link
Contributor

I'm happy to move towards the style you propose above. It does seem cleaner and more scalable.

@JacquesCarette
Copy link
Contributor

Let me understand if I've understood this right. The context here seems to be that some modules introduces fundamental functionality (sometimes highly parametrized), while other modules are 'actually' creating a particular view of that functionality which is better-suited for working on particular tasks (by specializing to certain parameters, but also tailoring the exports in certain ways).

If that's an adequate description, then indeed this feels like a deeply pragmatic design approach. [It has the drawback that working simultaneously with the general version and the specific version can cause clashes -- but I would say that that is rare, will only be done by experts, and they ought to use qualified imports when doing that.]

In other words, I too agree. (But I have started to think more deeply about that 'design' paper, even though we should knock off the JOSS one first!)

@jamesmckinna
Copy link
Contributor Author

@JacquesCarette I think your understanding is correct (but in rather different terms than I might either have first thought of this, or expressed it... ;-)).

My concerns, such as they are, are two-fold:

  • conceptual: trying to understand how we approach 'inheritance' in the Algebra.Bundles and Relation.*.Bundles hierarchies... in the proposed new style, putting the public export of the Setoid properties after that of DecSetoid ensures that 'super' (as it were) on properties refers consistently to the correct 'super' sub-bundle of decSetoid, rather than some accidentally extensionally equivalent, moreover explicitly defined, collection of fields with the correct types;
  • practical: DRY, reducing LOC, etc. (which also is intimately concerned with avoiding 'accidental' engineering coincidences...)

@jamesmckinna
Copy link
Contributor Author

jamesmckinna commented Oct 1, 2024

Examples discussed here are tackled by #2490 but otherwise leaving the issue open as a library-design topic.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

No branches or pull requests

3 participants