Refactor base library structure and port additional Haskell functions#456
Refactor base library structure and port additional Haskell functions#456loki259 wants to merge 8 commits intoagda:masterfrom
Conversation
This commit reorganizes large parts of the Agda2Hs base library to separate primitive type class definitions from higher-level utility functions and to align the module structure more closely with the corresponding hierarchy in Haskell. Key changes include: • Utility functions previously defined in Prim modules (e.g. Prim.String, Prim.Functor, Prim.Foldable, Prim.Monad, Prim.List) were moved to new modules in the Data and Control namespaces. • Introduced new modules mirroring the Haskell ecosystem, including: - Data.String - Data.Functor - Data.Foldable - Data.Traversable - Data.List - Control.Applicative - Control.Monad • Refactored several primitive modules so they now primarily contain class definitions and minimal core functionality. • Reworked the IO instances for Functor, Applicative, and Monad to define them explicitly in terms of bindIO and returnIO. • Added missing type classes and instances: - Alternative - MonadFail - MonadPlus • Expanded several modules with additional functions ported from Haskell’s base library. • Updated imports and reexports throughout the codebase to reflect the new module structure. Due to the tight dependencies between these changes, they are grouped into a single commit. This change is intended to make the library structure more consistent with Haskell and simplify future additions of standard functions.
jespercockx
left a comment
There was a problem hiding this comment.
Thank you for the nice PR! Generally things look good but I have a few small requests for changes. Also, could you please investigate the failure on CI (at least the non-Nix ones).
I could use some help in fixing the issues responsible for the remaining test failures (as already posted on Zulip): When I reexport definitions in another module (which I did with a lot of the newly ported functions that are part of the Prelude but needed to be defined elsewhere) the Haskell files produced by Agda2Hs seem to import those definitions from the module where they were originally exported instead of from the module where the corresponding Agda file imports them from. Another issue I have is that type class instances are seemingly not reexported unless I list the instances explicitly along with the class definition in the using clause of the public import. Listing them is of course not the end of the world but it will make adding new instances a bit cumbersome in the future because the import lists for the respective module need to be adjusted wherever the new instance should also be reexported. |
|
You're not missing anything, proper re-exports are still on the todo-list (see #126). As a workaround I guess you could replace the re-exports by postulates for now, possibly together with an equality proof that these postulates are equal to the real versions (this is not a very nice solution but I can't really think of a better one atm). For exporting instances, I don't think it should be necessary to explicitly import them at all, just importing the module should be sufficient to bring them in scope for instance resolution on the Agda side. Or is the problem that they are somehow not exported on the Haskell side? |
|
Oh okay, I didn't see that there was already an issue for this reexport problem. or : ⦃ Foldable t ⦄ → t Bool → Bool
or = Haskell.Data.List.orThis avoids postulates and seems a bit simpler to me. What do you think? Regarding the instance exports: There is no problem on the Haskell side but on the Agda side I cannot just use |
Yes, if that works it's a much better solution!
I believe it should also be sufficient to just give a name to the module that you want to re-export the instances from, e.g. import Prim.Alternative
module Alternative = Prim.AlternativeCould you give that approach a try to see if if works? |
…roup` into its own module
|
Unfortunately, my approach of introducing explicit alias definitions in place of reexports didn't work as well as expected: On the positive side, I found a solution for the instance export problem: |
…ons to work around agda#126
|
Ah, that is unfortunate. It seems this is blocked on implementing re-exports properly then. I would like to look at it but I also have a few open issues in Agda itself I need to fix first for the release of 2.9, so I'm not sure when I'll be able to get to it. In case anyone else want to give it a go, I would be happy to provide some pointers. |
Summary
This PR reorganizes large parts of the Agda2Hs base library to better separate primitive definitions from higher-level utilities and to align the module structure more closely with the hierarchy found in the Haskell library.
In addition to the structural refactoring, several modules were expanded with additional definitions ported from Haskell.
Main changes
Introduced new modules mirroring the Haskell version of the library:
Data.StringData.FunctorData.FoldableData.TraversableControl.ApplicativeRefactored
Primmodules so they mainly contain class definitions and minimal primitive functionality:_<$>_,_<&>_,_$>_,voidfromPrim.FunctortoData.Functor_=<<_,mapM₋,sequence₋fromPrim.MonadtoControl.MonadandData.Foldableand movedbindIOfromPrim.MonadtoPrim.IOlines,words,unlines,unwordsfromPrim.StringtoData.StringPrim.Listexcept_++_,head,last,tail,init,maptoData.ListlengthNatfromPrimtoPrim.Listreverse,_!!ᴺ_,_!!_,lookupfromPreludetoData.ListAdded additional type classes and instances and refactored existing type class
definitions:
IOinstances (Functor,Applicative,Monad) so they are now defined explicitly in terms ofbindIOandreturnIO.Alternativeclass record and instances (defined in new modulePrim.Alternative)MonadPlusclass record and instances (defined in new modulePrim.MonadPlus)MonadFailfromPrim.Monadinto its own modulePrim.MonadFailand added instance forIOMonoidFirstandMonoidLastMonoidinstances inPrim.MonoidApplicativeto includeliftA2as additional method (with corresponding default record)Foldableto match the Haskell version (movingany,all,and,or,concat,concatMap,notElemtoData.Foldableand addingfold,foldMap',foldr',foldl',foldr1,foldl1,maximum,minimum)SemigroupfromPrim.Monoidinto its own modulePrim.SemigroupExpanded several modules with additional definitions ported from Haskell (still missing definitions are listed in a comment at the end of the respective file):
Control.Monad(also changed signature of existingguarddefinition to match the Haskell version)Data.List(also updated the definition ofnuband removed some property proofs based on the outdated definition)Data.FunctorData.FoldableData.TraversableControl.ApplicativePreludeby updating module imports (also updated documentation of missing definitions from the Haskell prelude)Updated imports and reexports throughout the codebase to reflect the new module structure
Motivation
The goal of these changes is to make the structure of the library more consistent with the organization familiar from Haskell, while keeping the
Primmodules focused on primitive definitions. This separation also makes it easier to extend the library with additional standard definitions in the future and avoids many cyclic module dependencies when reusing definitions from other parts of the library.Notes
Because many of the refactorings depend on each other (often due to running into problems with cyclic imports), the changes are grouped into a single commit.