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

Divide Num into separate traits #8049

Closed
wants to merge 4 commits into from
Closed

Conversation

brendanzab
Copy link
Member

As part of the numeric trait reform (tracked in issue #4819), I have replaced Num with three traits, named according to mathematical conventions.

pub trait Semiring: Eq
                  + Add<Self,Self>
                  + Mul<Self,Self>
                  + Zero + One {}

pub trait Ring: Semiring
              + Neg<Self>
              + Sub<Self,Self> {}

pub trait Field: Ring
               + Div<Self,Self>
               + Rem<Self,Self> {
    pub fn recip(&self) -> Self;
}

You might think this is a tad excessive, but it's useful when you want to define these traits on other mathematical structures such as vectors and quaternions that don't satisfy all the operations required by the old Num.

I have also renamed Orderable to OrderedRing, which is the correct mathematical name. It should really require TotalOrd, but we are constrained by the fact that it is not impled by floats.

…OrderedRing.

These names follow the mathematical conventions. The greater fidelity of these traits allows them to be used on other mathematical structures such as vectors and quaternions.
@brson
Copy link
Contributor

brson commented Jul 25, 2013

Please wait for further discussion. Don't r+ yet.

@brendanzab
Copy link
Member Author

@brson yeah, this could be a tad contentious.

@bluss
Copy link
Member

bluss commented Jul 25, 2013

These traits are not useful for vector fields as written, you need both a vector and a scalar type.

EDIT 1:

This is a point trait from actual code. A point is a vector in a normal euclidean space.

/* Element of a Vector Space over scalar field F: 
 * Additive Abelian Group and multiplication with scalar */
pub trait Point<F> : Eq +
             Zero + Add<Self,Self> + Sub<Self,Self> + Neg<Self> +
             Mul<F,Self> + Div<F,Self> {}

EDIT 2

So vector fields don't have One (but require a scalar field that has a One) and vector fields support Mul<F, Self> etc.

Also we need to sure if we want Ring or Commutative Ring/CRing (most commonly used). A group trait at all is maybe not useful since each set has many ways of forming groups over different operators. An AdditiveAbelianGroup trait might be useful though.

@brendanzab
Copy link
Member Author

@blake2-ppc could you expand on that? What changes would you suggest? Could you post a snippet?

@brendanzab
Copy link
Member Author

@huonw @jensnockert: thoughts?

@brendanzab
Copy link
Member Author

@blake2-ppc Thanks for the input. The difficulty is that we can't enforce commutativity in Rust so CRing could be misleading. This is especially important for parallelism. Perhaps we could have some automatic unit tests at compile time, like in Fortress, but that would require extra language features.

If we were to add Commutativity, it might be better to have them as separate lang item traits with the associated unit tests:

  • Associative: grouping doesn't matter
  • Commutative: order doesn't matter
  • Idempotent: duplicates don't matter
  • Identity: this value doesn't matter
  • Zero: other values don't matter

See my reddit comment on Guy Steele's lecture.

@bluss
Copy link
Member

bluss commented Jul 26, 2013

I'd factor it like this for vector algebra. I don't know if a separate CRing trait is useful; the simplest (least composite) traits are normally the most useful.

/* Normal integer and rationals algebras */
pub trait AdditiveMonoid : Zero + Add<Self,Self> {}
pub trait AdditiveAbelianGroup : AdditiveMonoid + Sub<Self,Self> + Neg<Self> {}
pub trait CRing : AdditiveAbelianGroup + Mul<Self,Self> + One {}
pub trait Field : CRing + Div<Self,Self> {}

impl<F: Zero + Add<F, F>> AdditiveMonoid for F {}
impl<F: AdditiveMonoid + Sub<F, F> + Neg<F>> AdditiveAbelianGroup for F {}
impl<F: AdditiveAbelianGroup + Mul<F, F> + One> CRing for F {}
impl<F: CRing + Div<F, F>> Field for F {}

pub trait ScalarMultiplication<F> : Mul<F, Self> + Div<F, Self> {}
impl<F, V: Mul<F, V> + Div<F, V>> ScalarMultiplication<F> for V {}

/* A Point is an element of a Vector Space over scalar field F */
pub trait Point<F: Field> : Eq + AdditiveAbelianGroup + ScalarMultiplication<F> {}

/*
 * AdditiveMonoid: You can .sum() this, with Ord these are non-negative edge weigths,
 * AdditiveAbelianGroup + Ord: You can .abs() this, general graph edge weights
 * Field: Simplest possible general Scalar/float/Num
 * 
 *  Point: is a vector space element so it applies to any usual scalar, graphical point, matrix.
 *  needs more traits for dot product, norm, distance, cross product, etc.
 */

@huonw
Copy link
Member

huonw commented Jul 26, 2013

I'm fully in support of following the mathematical algebraic structures hierarchy.

Pros

  • lots of history/"optimisation" of ideas
  • each level encapsulates useful properties
  • the names have precedent

Cons

  • mathematical jargon
  • the traits may not capture the well-defined mathematical concepts exactly, possibly causing confusion

(Although I think @blake2-ppc's Point should be Vector, drop the Eq (since, e.g., functions are Vectors too), and it'd be awesome if there was Module below Vector (this is probably pushing it a bit far), i.e.

pub trait Module<R: Ring>: AdditiveAbelianGroup + ScalarMultiplication<R> {}

pub trait Vector<F: Field>: Module<F> {}

</bikeshed>)

@huonw
Copy link
Member

huonw commented Jul 26, 2013

Also, I like the approach of some how indicating at least commutativity and associativity, to allow parallel map-reduce algorithms to Just Work. (Even if this is just by convention/naming: "we told you, it's your fault that this algorithm doesn't return what you expect".)

@erickt
Copy link
Contributor

erickt commented Jul 26, 2013

@huonw: I agree with using Vector. However, I'm not sure if we need Vectors and Matrices in the standard library. I think we can define the algebraic structures in libstd/libextra, and then leave Vectors/Matrices for external libraries.

@blake2-ppc / @bjz: Would defining these algebraic structures prevent us from being able to use @nikomatsakis's double-dispatch overloading trick so we could support operator overloading Matrix_Matrix and Matrix_Vector multiplication?

@auroranockert
Copy link
Contributor

I like the name http://en.wikipedia.org/wiki/Quasigroup, it doesn't imply associative.

@bluss
Copy link
Member

bluss commented Jul 26, 2013

Regarding Vector Space and Module, @huonw, I'm very against traits that do not have real use case. This includes some of the traits I listed in association with the Vector space; I'm not sure I favor adding all of those at all, I just wanted to elaborate for bjz (since vector spaces were mentioned in the PR text).

@brendanzab
Copy link
Member Author

@blake2-ppc I definitely think VectorSpace doesn't belong in the std. We just want a structure that folks can extend in the future. The challenge is to avoid the issues that have plagued the Haskell numerics.

@brendanzab
Copy link
Member Author

Might be a good reference: http://www.haskell.org/haskellwiki/Numeric_Prelude

@nikomatsakis
Copy link
Contributor

@erickt btw I don't think that the double dispatch trick should be necessary. Plan is to lift the limitation that requires it, though of course we haven't done so yet.

@pcwalton
Copy link
Contributor

This seems like a good candidate for a library in the "incubator", a la Clojure. The rapid evolution of libraries like scalaz shows that these abstract algebra libraries take time to mature. I'm totally in favor of this kind of experimentation, don't get me wrong, especially when it's motivated by a use case--I just don't want to freeze the interface too early.

@cartazio
Copy link
Contributor

@bjz one note about that numerical prelude lib in haskell that you've linked to is that the Haddock type docs are unreadable, you'll have to read the lib in source form to get the info out of it
http://hackage.haskell.org/package/algebra is another example haskell algebra lib, though less "complete" than the other

@brson
Copy link
Contributor

brson commented Jul 26, 2013

I am worried that this is making the num traits too detailed and complex, in a way that is not particularly useful but to a small audience. Frankly most of the names suggested here are kind of outrageous as core numeric traits for a general programming audience. I imagine there is not a lot of precedent for this factoring of the numeric types in other standard libraries, but I'd be happy to see some comparisons.

@auroranockert
Copy link
Contributor

@brson: I agree, we should try to minimize the complexity of the trait hierarchy, and only keep those traits that map to types we are likely to use, not approximations mathematical structures.

Using names such as Field confuses everyone since most types implementing Field won't actually be fields.

@brendanzab
Copy link
Member Author

Excellent feedback everybody! I greatly appreciate the honest critiques.

This seems like a good candidate for a library in the "incubator", a la Clojure. The rapid evolution of libraries like scalaz shows that these abstract algebra libraries take time to mature.

@pcwalton I'm now thinking now it might be useful to have an external, generalized numeric prelude.

#[no_implicit_prelude];
extern mod numeric;
use numeric::prelude::*;

I don't know if this should be in extern, but I'm willing to set up my own repo for now. I agree this needs to be more nimble than what core can provide.

@brendanzab
Copy link
Member Author

Ok, in the light of the highly reasonable arguments against, I am going to close this pull, for now.

@brendanzab brendanzab closed this Jul 27, 2013
@brendanzab brendanzab deleted the num branch November 9, 2013 21:13
flip1995 pushed a commit to flip1995/rust that referenced this pull request Dec 2, 2021
Add test for pattern_type_mismatch.

This issue has been fixed by [commit](rust-lang/rust-clippy@8c1c763)
This PR is used for close rust-lang#7946(Fixes rust-lang#7946).

changelog: Add test for pattern_type_mismatch.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

9 participants