nikita-volkov / typeclasses

Explicit typeclasses for Elm
https://package.elm-lang.org/packages/nikita-volkov/typeclasses/latest/
MIT License
54 stars 3 forks source link

Just a PR to get your opinion on direction #7

Closed jonathanfishbein1 closed 2 years ago

jonathanfishbein1 commented 4 years ago

Hi Nikita,

I added some files, also my elm-format formatted some existing files. Let me know what you think and if you'd like some things done differently

Jonathan

jonathanfishbein1 commented 4 years ago

I've updated my master branch with the changes. I'm not entirely sure what I should do next though I don't have too much experience. Should I submit another PR. Do you have some guidance?

nikita-volkov commented 4 years ago

Are you ready for this to be merged or are you still making changes?

jonathanfishbein1 commented 4 years ago

Group is done but I guess I still need to flesh out ring and add field. Looking at the my code I see I still have a reference to CommutatitveMonoid in Semiring. I'm surprised I was able to compile last night?

jonathanfishbein1 commented 4 years ago

What do you think about having a Semiring and Ring module?

nikita-volkov commented 4 years ago

Up to you. In my FP experience I've never had a need for them.

jonathanfishbein1 commented 4 years ago

Maybe just for my own education. I'd like to fold in my existing elm-field package and then deprecate that one

jonathanfishbein1 commented 4 years ago

What do you think about merging in the group functionality and the test suite? I can elaborate on Semiring and Ring as I learn more about them?

jonathanfishbein1 commented 4 years ago

What do you think about adding Magma?

https://en.wikipedia.org/wiki/Magma_(algebra)

nikita-volkov commented 4 years ago

What would the instances be?

jonathanfishbein1 commented 4 years ago

They are mostly obscure examples but I'm enjoying the learning process

https://math.stackexchange.com/questions/779507/can-you-give-me-some-concrete-examples-of-magmas

a∗b:=a+2b

as a binary operator is a little strange.

I'm working my way through this course but it's taking a while! Hope you don't mind

https://www.youtube.com/watch?v=lx3qJ-zjn5Y&list=PLmU0FIlJY-Mn3Pt-r5zQ_-Ar8mAnBZTf2

jonathanfishbein1 commented 4 years ago

What do you think about

type CommutativeSemigroup a
= CommutativeSemigroup (Semigroup a)

within the Semigroup module?

I create a branch with an example

https://github.com/jonathanfishbein1/typeclasses/tree/feature/CommutativeSemigroupType

nikita-volkov commented 4 years ago

What's the practical benefit compared to only having Semigroup?

jonathanfishbein1 commented 4 years ago

I guess you'd have to opt in to be a CommutativeSemigroup and so there would be additional semantic meaning. I'm thinking about how people will create a wrapper type for an ID such as

type PersonId = PersonId Int

so as to convey it's not an int that you're supposed to do arithmetic with.

The test suite was able to be cleaned up a bit. For CommutativeMonoids I was able to remove the property tests that check whether the identity value is commutative with everything because there is a test in the SemigroupTests that tests whether the whole set is commutative with itself.

The tighter types also snake up the composition chain to Ring where I can say the addition portion is an AbelianGroup and an AbelianGroup features a CommutativeMonoid which features a CommutativeSemigroup.

I'm not wedded to the idea so just looking to play around with it, see what you think and get some hands on practice with these concepts.

jonathanfishbein1 commented 4 years ago

What do you think?

nikita-volkov commented 4 years ago

Oh. Sorry. I forgot to reply. I'm up for having CommutativeSemigroup. Just please stick to the convention of having each class in its own module.

jonathanfishbein1 commented 4 years ago

Ok so I've updated the code separating, the different types into different modules. I added the Magma type because I wanted to expose CommutativeSemigroup types as Semigroups. Previously CommutativeSemigroup was defined as

type CommutativeSemigroup a = Typeclasses.Classes.Semigroup.Semigroup a

but when I went to try and expose CommutativeSemigroups as Semigroups I was getting the circular reference error. I've also added the Field type. I think I have the necessary functionality to incorporate this library into my other ones. The most recent changes are here. Let me know what you think!

https://github.com/jonathanfishbein1/typeclasses/tree/feature/Field

jonathanfishbein1 commented 4 years ago

what do you think?

nikita-volkov commented 4 years ago

I think that Magma is redundant for the same reasons as in the following discussion: https://github.com/purescript/purescript/issues/302#issuecomment-38013787.

Another thing to notice is that aliasing with the ADT type-wrappers breaks the convention of referring to parent classes thru fields, which we already have established in other classes. IOW, the Field definition should have been like this:

type alias Field a = { commutativeRing : CommutativeRing a }

But then I'm also doubting the value of Field altogether, because I also don't support declaring new typeclasses, that simply alias others, which is the case with Field. It adds complexity to the library design without any traceable benefit. Did you have any particular purpose with that?

jonathanfishbein1 commented 4 years ago

Hi Nikita,

Thank you for your response and the purescript resource. I agree with your idea about Magma, I've modified the the code to remove it. I'm still working on the same branch right now

https://github.com/jonathanfishbein1/typeclasses/tree/feature/Field

Give me some time to process your ideas about Field, I'm still working through the lecture on abstract algebra.

jonathanfishbein1 commented 4 years ago

I'm still plugging along my course on abstract algebra! taking a little longer than I would have hoped to learn the material

jonathanfishbein1 commented 3 years ago

Hi Nikita,

Sorry for taking so long, I have been learning abstract algebra this entire time, I'm now realizing I may not need to know all the details of an isomorphism to finish this PR! I agree that wrapping commutativeRing in a type Field is overkill. I like the type alias Field definition. If other programmers want to use this library I think most of the time they will reach for Field, it's more common rather than CommutativeRing. I think type alias definition is a good compromise between being overly specific and adding complexity with type Field and only exposing commutativeRing which other programmers won't immediately recognize. Interested to hear what you think

Jonathan

jonathanfishbein1 commented 3 years ago

what do you think?

nikita-volkov commented 3 years ago

Sorry for not responding earlier. I have to admit this PR is turning into a burden for me. Every time I come back it takes a bigger mental effort to reestablish the context, which I need to be able to answer to you. The reason is that this PR has actually turned into a research project of its own.

My practice shows that having PRs be small and focused is the recipe of avoiding such issues. Ideally PR should address one atomic subject at a time.

I see two ways of resolving this issue:

  1. We stop adding features or researching, polish the code up and merge the PR.

  2. You start your own project with this code. Possibly introducing a dependency on this one. And you're free to experiment however fits you.

jonathanfishbein1 commented 3 years ago

Hi Nikita,

Thanks for getting back. I can work on my PR practices, I actually haven't done many PRs. I would prefer option 1 but open to either. Let me know how you would like the code polished!

Jonathan

nikita-volkov commented 3 years ago

A prerequisite for a successful project (not just in engineering) is for it to have a clear goal. It must solve a clearly defined problem and it must be focused on it.

The goal that I have for this library is for it to solve practical problems that cannot be solved without typeclasses. The goal is not about trying to marry Elm with Category Theory. Therefore occasional introduction of abstractions from Category Theory is merely a side-effect of the goal.

Having the goal set we can describe the audience of the library. The way I see it, it is advanced Elm users who have approached the limit of what can be done in Elm without typeclasses. It is practical users, who do production code, it is not academia.

This audience may have no idea about what Category Theory is and it clearly doesn't want it pushed down its throat. But this audience is open to new experience. We can exploit that and gradually lead it towards the beautiful world of categories thru practical use. Yes, Category Theory is beautiful and it is just astonishing how many practical things it can provide abstractions for, but we need to stay focused and not overwhelm people by screaming abstractions at them.

With that said I'm honestly concerned about users getting overwhelmed with an explosion of definitions, especially so in the light of Elm in whole being targeted at JS refugees, not academia.

That's why I believe we should only add abstractions after we prove that there is a need for them. I.e., after we prove that there are problems that cannot be solved without the set of abstractions that we already have.

This is why I suggest to remove all aliasing abstractions such as everything prefixed with Abelian and Commutative, because they can be seen as special cases of Group, Monoid and Semigroup.

If there is a case where a type can have different instances for e.g., Semigroup and Abelian semigroup, it can instead have two instances of Semigroup. This would reduce the mental burden on the users of the package.

We also need to be careful about the documentation. If, say, we introduce Ring, the documentation shouldn't just say "It's Ring". Ideally, it should explain what it is and provide practical examples of what it's useful for. Such practice also provides a tool for us: if we struggle to find practical examples for an abstraction, it should serve as a large red flag that the abstraction wouldn't be used in practice.

This project can turn into a successful entry drug into Category Theory but it can only happen if it has users. So approaching users correctly is the priority.

I hope you get me now. If you agree with this vision, I'll be happy for it to turn into our collective project. If you feel like you have different goals (e.g., research on marrying Elm with Category Theory) it probably is better for you to just make your own project out of it.