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

Add type classes and .Instance modules declaring their instances #1332

Open
1 of 17 tasks
jespercockx opened this issue Oct 23, 2020 · 6 comments
Open
1 of 17 tasks

Add type classes and .Instance modules declaring their instances #1332

jespercockx opened this issue Oct 23, 2020 · 6 comments

Comments

@jespercockx
Copy link
Member

jespercockx commented Oct 23, 2020

During the Agda meeting, I identified the following list of typeclasses for which it would be nice to have a .Instances module declaring their instances (some of these would also need the typeclass itself being added to the library):

  • Show (turning things into strings), see Show functions for all the datatypes #431
  • Eq (decidable equality)
  • Ord (decidable ordering)
  • Number (types that admit natural number literals)
  • Fractional (types that admit floating point literals)
  • Quotable (types that we know how to turn into reflected syntax)
  • IsMagma (from Algebra.Structures)
  • IsSemigroup (from Algebra.Structures)
  • IsMonoid (from Algebra.Structures)
  • ... (other structures from Algebra.Structures)
  • Foldable, see Add Haskell's Foldable #1099
  • TraversableA and TraversableM
  • WithDefault (for types with a "default" element), see Add WithDefault construct #1450
  • ProofIrrelevant (for types with at most one element)
  • HasHLevel (for types of a finite h-level)

The following monad transformers should also be given instances of the typeclasses they inhabit:

  • StateT
  • ReaderT

I didn't want to spam the issue tracker with new issues, so I have bundled them here into one. But it would be easy to divide this work among multiple people!

@jespercockx
Copy link
Member Author

See also #559 for the more general discussion on instance arguments in the standard library.

@gallais
Copy link
Member

gallais commented Oct 24, 2020

See #569 #431 for discussions on what a Show class would look like.

jespercockx added a commit to jespercockx/agda-stdlib that referenced this issue Nov 1, 2020
@MatthewDaggitt MatthewDaggitt added this to the v2.0 milestone Jul 11, 2021
@MatthewDaggitt MatthewDaggitt modified the milestones: v2.0, v3.0 May 3, 2022
@WhatisRT
Copy link
Contributor

WhatisRT commented May 4, 2022

We agreed yesterday that moving all the names like _+_, map, etc. that would clash with type classes (and that do clash with other modules right now) into a separate module that isn't imported with everything else is probably a good thing, even if we don't have type classes in v2.0.

We were also discussing the question of using 'algebraic' type classes (like Monoid) versus using 'syntactic' type classes (like has_add in Lean) but didn't come to a conclusion. Orestis just pointed out that using the renaming fields of the algebraic classes to something like + might be a better match for Agda than the style that Lean uses.

@MatthewDaggitt
Copy link
Contributor

We agreed yesterday that moving all the names like +, map, etc. that would clash with type classes (and that do clash with other modules right now) into a separate module that isn't imported with everything else is probably a good thing, even if we don't have type classes in v2.0.

Err I'm afraid I'm not quite sure that's what I got. I thought that the conclusion was that we should have a separate module that imported everything you need for using instances + all the non-clashing original content as well. I don't think we need to go so far as to create a new common base module, which is what I think you're proposing?

Orestis just pointed out that using the renaming fields of the algebraic classes to something like + might be a better match for Agda than the style that Lean uses.

I'm afraid I don't quite remember this point? I thought Oreistis was saying that that was the better solution if one didn't want to use type-classes. Personally I'm strongly in favour of the syntactic style, as the latter doesn't involve heavy-weight dependencies on the Properties files.

@WhatisRT
Copy link
Contributor

WhatisRT commented May 4, 2022

Err I'm afraid I'm not quite sure that's what I got. I thought that the conclusion was that we should have a separate module that imported everything you need for using instances + all the non-clashing original content as well. I don't think we need to go so far as to create a new common base module, which is what I think you're proposing?

As I see it there are two approaches. Using Data.Nat as an example and making up some names, we could either have two modules Data.Nat and Data.Nat.Instance where they both export the same names but with one of them using instance arguments and the other not, or there could be three modules, Data.Nat, Data.Nat.Instance and Data.Nat.NoInstance, where the first one exports no names that clash with the other two. To me the latter approach seems more natural, but you're saying the former is a better pick? I'm fine either way.

I'm afraid I don't quite remember this point? I thought Oreistis was saying that that was the better solution if one didn't want to use type-classes. Personally I'm strongly in favour of the syntactic style, as the latter doesn't involve heavy-weight dependencies on the Properties files.

Yes, my writing was probably a bit unclear. This is a new point that came up this morning, and I'm actually still unsure about my opinion. I think I found an issue with this idea of renaming - maybe it's time to write an example module that demonstrates this issue.

It might also be worth pointing out that Lean does both, it has syntactic classes like has_add, but also algebraic ones like Ring. There are some annoying aspects to this mixing, but it generally works quite well.

@MatthewDaggitt
Copy link
Contributor

As I see it there are two approaches. Using Data.Nat as an example and making up some names, we could either have two modules Data.Nat and Data.Nat.Instance where they both export the same names but with one of them using instance arguments and the other not, or there could be three modules, Data.Nat, Data.Nat.Instance and Data.Nat.NoInstance, where the first one exports no names that clash with the other two.

I have to confess I struggle to see the concrete benefits of the latter?

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

4 participants