Join GitHub today
GitHub is home to over 31 million developers working together to host and review code, manage projects, and build software together.
Sign up`Combine` trait for string and collection concatenation #203
Conversation
This comment has been minimized.
This comment has been minimized.
bgamari
commented
Aug 17, 2014
|
I think the move away from |
pnkfelix
referenced this pull request
Aug 17, 2014
Closed
feature request: `Compose` trait for strings and functions #16541
This comment has been minimized.
This comment has been minimized.
|
@apoelstra IMO this could very well have gone up on discourse first. (I saw your comment on rust-lang/rust#16541 that mentioned potentially doing that.) My opinion is that draft RFC's can go through rounds of improvement on discourse first. But then again, perhaps you are more eager to see a quick yay/nay rather than going through discourse-based bike-shedding before coming here. As for the operator itself: Have you considered that going forward we probably want to encourage use of |
This comment has been minimized.
This comment has been minimized.
|
I think we should go with @pnkfelix, yes I do believe we need |
This comment has been minimized.
This comment has been minimized.
@apoelstra What would be the signature of the |
This comment has been minimized.
This comment has been minimized.
|
According to the wikipedia article on Monoids, especially the part on "Monoids in computer science", CS people tend to utilize monoids with "accumulating" or "folding" operations. And string concatenations and function compositions are "accumulating" operations. We have other uses for the name The problem is, does "Accumulate" imply the involvement of more than two elements? Sorry that I am on my phone and cannot edit the previous post. |
This comment has been minimized.
This comment has been minimized.
|
@japaric, or |
This comment has been minimized.
This comment has been minimized.
I'm in favor of either |
This comment has been minimized.
This comment has been minimized.
|
@japaric, I think And |
This comment has been minimized.
This comment has been minimized.
|
@japaric @pnkfelix Yes, SOP for discourse is endless bikeshedding on such things as This RFC came out of several IRC discussions with people familiar with Rust and the problem space, and has already undergone revisions because of it. For example I wanted |
This comment has been minimized.
This comment has been minimized.
bluss
commented
Aug 17, 2014
|
The RFC should mention using |
This comment has been minimized.
This comment has been minimized.
The current RFC only proposes |
This comment has been minimized.
This comment has been minimized.
|
Oh! FWIW the signature of Edit2: Thanks for the suggestion @bluss. Updated RFC. |
apoelstra
added some commits
Aug 17, 2014
olivren
reviewed
Aug 17, 2014
| `Compose` should also be used for function compositions, at least for single-argument | ||
| functions `T->T`. How would this interact with our current/future coherence rules? | ||
|
|
||
| Where else should `Compose` be used? |
This comment has been minimized.
This comment has been minimized.
olivren
Aug 17, 2014
Compose could be used on an Iterator, as a synonym of the chain method. It could also be used on GenericPath, performing a join.
This comment has been minimized.
This comment has been minimized.
SiegeLord
commented
Aug 17, 2014
|
I am very strongly against any requirement of commutativity on |
This comment has been minimized.
This comment has been minimized.
bgamari
commented
Aug 17, 2014
|
Andrew Poelstra notifications@github.com writes:
|
This comment has been minimized.
This comment has been minimized.
bgamari
commented
Aug 17, 2014
|
SiegeLord notifications@github.com writes:
|
This comment has been minimized.
This comment has been minimized.
|
@apoelstra, I think all collection types that implement Extendable are eligible for |
This comment has been minimized.
This comment has been minimized.
|
It depends exactly what we define commutativity to mean. For expression templates, the memory of |
This comment has been minimized.
This comment has been minimized.
|
+1 to the general idea. I like having the separation just for a intuitive scanning of code. |
This comment has been minimized.
This comment has been minimized.
SiegeLord
commented
Aug 18, 2014
|
Yes, what huonw said. One more issue I thought of today is types declared outside of |
This comment has been minimized.
This comment has been minimized.
bgamari
commented
Aug 18, 2014
|
@SiegeLord a fair point. |
This comment has been minimized.
This comment has been minimized.
|
@SiegeLord Yes, I would consider an operation to be commutative even if one of the commutations can't be written down. This throws a wrench in my dreams of having unit tests for commutativity, but those were already broken by the fact that you can define The main reason is that I consider "one of the commutations can't be written down" to be a bug in the current trait definitions, which would be fixed by multiple dispatch. The two type parameters to (most) binary operators should be treated on equal footing. |
This comment has been minimized.
This comment has been minimized.
reem
commented
Aug 18, 2014
|
I am strongly in favor of this RFC. Rust has, should absolutely be implementing the best traits defined in languages like Haskell that abstract massively popular patterns. |
This comment has been minimized.
This comment has been minimized.
|
@CloudiDust Good call on |
This comment has been minimized.
This comment has been minimized.
|
@liigo, we are not creating another operator, EDIT: Grammar. |
This comment has been minimized.
This comment has been minimized.
|
@liigo, also, just because something is widespread in mainstream languages, doesn't automatically mean it is right, or Rust should adopt it. Unconstrained |
This comment has been minimized.
This comment has been minimized.
|
@liigo I think a reason against However their |
This comment has been minimized.
This comment has been minimized.
|
@CloudiDust My last comment focused on "common languages", not ++ or +. (I'm not against ++) |
This comment has been minimized.
This comment has been minimized.
|
@liigo "common language" means ordinary English. In English, "addition" refers to a commutative operator. As for "you can abuse I am not proposing that we abuse |
This comment has been minimized.
This comment has been minimized.
|
@apoelstra Yes I see. thanks for you explanation. |
This comment has been minimized.
This comment has been minimized.
|
@liigo, I was just pointing out a possible reason that was against |
mahkoh
reviewed
Sep 15, 2014
| Users who want an abelian group can then use `Add+Zero+Neg` (or `Add+Zero+Sub`, | ||
| this ambiguity should probably be addressed in a later RFC related to fixing the | ||
| numeric traits once we have associated items); users who want an arbitrary group | ||
| can use `Mul+One+Div`; users who want a monoid can use `Combine+Default`, etc. |
This comment has been minimized.
This comment has been minimized.
mahkoh
Sep 15, 2014
Contributor
What if I want to write a generic method that works on all groups? According to this I would write
fn f<T: Mul+One+Div>(...Naturally this algorithm also works for all abelian groups, but how does the compiler know that? The biggest argument for this RFC seems to be that abstract algorithms can make certain assumptions, but does this scheme even support abstract algorithms?
This comment has been minimized.
This comment has been minimized.
|
I'd find it a bit more natural to remove the
One example: trait Field {
fn zero() -> Self;
fn one() -> Self;
fn add(self, other: &Self) -> Self;
fn sub(self, other: &Self) -> Self;
fn neg(self) -> Self {
Field::zero().sub(&self)
}
fn mul(self, other: &Self) -> Self;
fn div(self, other: &Self) -> Self;
fn inv(self) -> Self {
Field::one().div(&self)
}
}As you can see, the functions take Then comes the compiler magic: Every type can implement at most one of these traits and the compiler knows, e.g., that every monoid is also a magma. I'm not yet sure if there's really a good story here. The biggest problem is that PS: |
This comment has been minimized.
This comment has been minimized.
|
Please god don't add group-theoretic categories to Rust's standard library. Monoid/Monad/Functor has caused untold educational pain in the Haskell world. If we have to have them, they should at least have decent names that relate to what they actually are. |
This comment has been minimized.
This comment has been minimized.
thestinger
commented
Sep 15, 2014
|
If operating overloading is intended to be abused for creating an arbitrary DSL, then it shouldn't be tied to traits. Traits without guarantees aren't useful, because it's not possible to write correct generic code with them. I think it should be tied to traits and adding better support for creating a DSL is a problem for language improvements to deal with. The ability to define custom operators or infix call sugar would alleviate the need to abuse the basic operators. The I don't think new operators should be added as special cases. Please just propose a general solution rather than adding more and more built-in operators. |
This comment has been minimized.
This comment has been minimized.
Don't worry, those really have nothing to do with what I've described above. |
This comment has been minimized.
This comment has been minimized.
SiegeLord
commented
Sep 15, 2014
I really don't think operator abuse is that clear cut. E.g. it might be useful to have a trait which adds an overload for So it seems obvious to me that it's better to divorse operator overloading from traits (i.e. do what @mahkoh suggested except perhaps with less jargon and compiler magic). That way we can have two traits, commutative |
This comment has been minimized.
This comment has been minimized.
|
@SiegeLord If "commutative multiplication" refers to a group operator, then addition can be used. If addition is already taken, presumably we are in a ring or something, and the appropriate way to approach this is to have traits I also don't think this sort of thing belongs in the standard library, but rather in some external "mathtypelib" which would have the full gamut of algebraic structures. All I'm trying to do with this RFC is make sure the stdlib doesn't discourage that by setting a bad example. |
This comment has been minimized.
This comment has been minimized.
SiegeLord
commented
Sep 15, 2014
|
@apoelstra That seems completely opposite of what you suggest in the RFC, however. If you want to defer the semantics to those mathy traits, then the operator overloading traits should have no semantics at all, and should not be used in generic code directly (i.e. you'd use your |
This comment has been minimized.
This comment has been minimized.
thestinger
commented
Sep 15, 2014
|
I think it's an awful workaround for the lack of better language features. Reusing the same few names or operators for different operations is poor API design. It should be possible to define custom operators if operators are going to be used as sugar for cases not meeting sane requirements for the mathematical traits. |
This comment has been minimized.
This comment has been minimized.
SiegeLord
commented
Sep 15, 2014
I don't disagree, but in the realm of syntax sugar where there is enormous pressure to pick very short names, this will be inevitable, even with custom operators. |
This comment has been minimized.
This comment has been minimized.
|
@SiegeLord Hmm, you're right, my "all I'm trying to do" comment is a bit disingenuous. I definitely think that On the other hand, I worry about the slide into Haskellism where we are intimidating new users with too much abstract algebra, which is why I don't advocate having My feeling is that commutativity and associativity are okay to enforce where appropriate, because I think that ordinary programmers are very familiar with these concepts. |
This comment has been minimized.
This comment has been minimized.
|
I think a sensible middle ground, which mostly tracks the current approach, might be:
This allows full syntactic flexibility for EDSLs while still retaining sanity for normal generic code. The main drawback is a readability hit: you wouldn't be able see the use of an operator in arbitrary code and assume that it has any particular types or laws; if it's generic code you would have to look at what trait bounds are being required, and for non-generic code you would need to be familiar with the type it's being used with. (Of course, community pressure can still be applied to discourage truly egregious abuses.) Tying the operator overloads directly to laws as @thestinger suggests is appealing, and if that's the road we eventually choose to go down, it wouldn't necessarily bother me. I think that's a perfectly sensible option as well. But not even GHC manages to entirely hold the line on this. They have an extension called |
This comment has been minimized.
This comment has been minimized.
thestinger
commented
Sep 16, 2014
|
Why should they be traits if they're not meant to be used as traits? It doesn't make much sense to me. If it's not doing the same thing, it shouldn't use the same name / operator. The debate is already over for |
This comment has been minimized.
This comment has been minimized.
|
It's a mechanism which already exists and works for the purpose, basically. The problem is that "the same thing" is too general a concept to be captured precisely in the type system (or at least in ours). An EDSL in which the |
This comment has been minimized.
This comment has been minimized.
thestinger
commented
Sep 16, 2014
|
The traits for overloading |
aturon
force-pushed the
rust-lang:master
branch
from
4c0bebf
to
b1d1bfd
Sep 16, 2014
glaebhoerl
referenced this pull request
Oct 8, 2014
Open
Important traits which don't need HKTs #370
alexcrichton
force-pushed the
rust-lang:master
branch
from
b9e2b8c
to
5020131
Oct 29, 2014
This comment has been minimized.
This comment has been minimized.
|
ping @huonw |
aturon
added
the
T-libs
label
May 22, 2015
This comment has been minimized.
This comment has been minimized.
|
This RFC has been inactive for quite some time now, so I'm going to close this. It would be good to take a fresh look at this RFC with today's modern standard library, especially with respect to ops traits and how the ownership of their arguments have changed. I'd definitely believe there's still a place for a trait like this in the standard library, but it would be useful to start anew! |
apoelstra commentedAug 17, 2014
Rendered: https://github.com/apoelstra/rfcs/blob/compose-trait/active/0000-compose-trait.md
cc rust-lang/rust#16541