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

Instructions incomplete/incorrect on how to define an additive group #63

Open
jeremysalwen opened this issue Feb 1, 2019 · 3 comments

Comments

@jeremysalwen
Copy link

If I define an additive group according to the instructions in the documentation, it still will not satisfy the AdditiveGroup trait, and I can't do addition with it (e.g. element + element).

use alga::general::{AbstractMagma, Additive, AdditiveGroup, Identity, Inverse}; // 0.7.2
use alga_derive::Alga; // 0.7.1

#[derive(Alga, Clone, Copy, PartialEq, Debug)]
#[alga_traits(Group(Additive))]
pub struct TrivialGroup;

impl AbstractMagma<Additive> for TrivialGroup {
    fn operate(&self, _right: &Self) -> Self {
        TrivialGroup {}
    }
}

impl Identity<Additive> for TrivialGroup {
    fn identity() -> Self {
        TrivialGroup {}
    }
}

impl Inverse<Additive> for TrivialGroup {
    fn inverse(&self) -> Self {
        TrivialGroup {}
    }
}

struct Bar<T: AdditiveGroup> {
    t: T,
}

fn main() {
    let foo = Bar::<TrivialGroup> { t: TrivialGroup {} };
}

Gives the error:

error[E0277]: the trait bound `TrivialGroup: num_traits::identities::Zero` is not satisfied
  --> src/main.rs:31:15
   |
31 |     let foo = Bar::<TrivialGroup> { t: TrivialGroup {} };
   |               ^^^^^^^^^^^^^^^^^^^ the trait `num_traits::identities::Zero` is not implemented for `TrivialGroup`
   |
   = note: required because of the requirements on the impl of `_ALGA_DERIVE_TrivialGroup::_alga::general::AdditiveLoop` for `TrivialGroup`
   = note: required because of the requirements on the impl of `_ALGA_DERIVE_TrivialGroup::_alga::general::AdditiveGroup` for `TrivialGroup`
note: required by `Bar`
  --> src/main.rs:26:1
   |
26 | struct Bar<T: AdditiveGroup> {
   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error[E0277]: the trait bound `TrivialGroup: std::ops::Neg` is not satisfied
  --> src/main.rs:31:15
   |
31 |     let foo = Bar::<TrivialGroup> { t: TrivialGroup {} };
   |               ^^^^^^^^^^^^^^^^^^^ the trait `std::ops::Neg` is not implemented for `TrivialGroup`
   |
   = note: required because of the requirements on the impl of `_ALGA_DERIVE_TrivialGroup::_alga::general::ClosedNeg` for `TrivialGroup`
   = note: required because of the requirements on the impl of `_ALGA_DERIVE_TrivialGroup::_alga::general::AdditiveLoop` for `TrivialGroup`
   = note: required because of the requirements on the impl of `_ALGA_DERIVE_TrivialGroup::_alga::general::AdditiveGroup` for `TrivialGroup`
note: required by `Bar`
  --> src/main.rs:26:1
   |
26 | struct Bar<T: AdditiveGroup> {
   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error[E0277]: cannot subtract `TrivialGroup` from `TrivialGroup`
  --> src/main.rs:31:15
   |
31 |     let foo = Bar::<TrivialGroup> { t: TrivialGroup {} };
   |               ^^^^^^^^^^^^^^^^^^^ no implementation for `TrivialGroup - TrivialGroup`
   |
   = help: the trait `std::ops::Sub` is not implemented for `TrivialGroup`
   = note: required because of the requirements on the impl of `_ALGA_DERIVE_TrivialGroup::_alga::general::ClosedSub` for `TrivialGroup`
   = note: required because of the requirements on the impl of `_ALGA_DERIVE_TrivialGroup::_alga::general::AdditiveQuasigroup` for `TrivialGroup`
   = note: required because of the requirements on the impl of `_ALGA_DERIVE_TrivialGroup::_alga::general::AdditiveLoop` for `TrivialGroup`
   = note: required because of the requirements on the impl of `_ALGA_DERIVE_TrivialGroup::_alga::general::AdditiveGroup` for `TrivialGroup`
note: required by `Bar`
  --> src/main.rs:26:1
   |
26 | struct Bar<T: AdditiveGroup> {
   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error[E0277]: cannot subtract-assign `TrivialGroup` from `TrivialGroup`
  --> src/main.rs:31:15
   |
31 |     let foo = Bar::<TrivialGroup> { t: TrivialGroup {} };
   |               ^^^^^^^^^^^^^^^^^^^ no implementation for `TrivialGroup -= TrivialGroup`
   |
   = help: the trait `std::ops::SubAssign` is not implemented for `TrivialGroup`
   = note: required because of the requirements on the impl of `_ALGA_DERIVE_TrivialGroup::_alga::general::ClosedSub` for `TrivialGroup`
   = note: required because of the requirements on the impl of `_ALGA_DERIVE_TrivialGroup::_alga::general::AdditiveQuasigroup` for `TrivialGroup`
   = note: required because of the requirements on the impl of `_ALGA_DERIVE_TrivialGroup::_alga::general::AdditiveLoop` for `TrivialGroup`
   = note: required because of the requirements on the impl of `_ALGA_DERIVE_TrivialGroup::_alga::general::AdditiveGroup` for `TrivialGroup`
note: required by `Bar`
  --> src/main.rs:26:1
   |
26 | struct Bar<T: AdditiveGroup> {
   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error[E0277]: cannot add-assign `TrivialGroup` to `TrivialGroup`
  --> src/main.rs:31:15
   |
31 |     let foo = Bar::<TrivialGroup> { t: TrivialGroup {} };
   |               ^^^^^^^^^^^^^^^^^^^ no implementation for `TrivialGroup += TrivialGroup`
   |
   = help: the trait `std::ops::AddAssign` is not implemented for `TrivialGroup`
   = note: required because of the requirements on the impl of `_ALGA_DERIVE_TrivialGroup::_alga::general::ClosedAdd` for `TrivialGroup`
   = note: required because of the requirements on the impl of `_ALGA_DERIVE_TrivialGroup::_alga::general::AdditiveSemigroup` for `TrivialGroup`
   = note: required because of the requirements on the impl of `_ALGA_DERIVE_TrivialGroup::_alga::general::AdditiveMonoid` for `TrivialGroup`
   = note: required because of the requirements on the impl of `_ALGA_DERIVE_TrivialGroup::_alga::general::AdditiveGroup` for `TrivialGroup`
note: required by `Bar`
  --> src/main.rs:26:1
   |
26 | struct Bar<T: AdditiveGroup> {
   | ^^^^^^^^^^^^^^^^^^^^^^^^^^^^

See also: https://stackoverflow.com/questions/54303935/defining-additivegroup-with-alga-crate

@WaDelma
Copy link
Contributor

WaDelma commented Feb 1, 2019

There is some confusion here: alga_derive implements AbstractGroup<Additive> for you which is different from AdditiveGroup which requires the extra Zero, Neg, SubAssign, AddAssign traits to be implemented.

These restrict to what kind of things it can accept, but as a trade make using it cleaner

The alga_derive documentations doesn't talk about this explicitly though.

@jeremysalwen
Copy link
Author

I think I understand, but are you sure that list of required traits is complete? The compiler is complaining, I think it wants me to implement Add as well. So it seems like in total, in order to define an AdditiveGroup I need all this boilerplate?

#[derive(Alga, Clone, Copy, PartialEq, Debug)]
#[alga_traits(Group(Additive))]
pub struct TrivialGroup;

impl AbstractMagma<Additive> for TrivialGroup {
    fn operate(&self, _right: &Self) -> Self {
        TrivialGroup {}
    }
}

impl Identity<Additive> for TrivialGroup {
    fn identity() -> Self {
        TrivialGroup {}
    }
}

impl Inverse<Additive> for TrivialGroup {
    fn inverse(&self) -> Self {
        TrivialGroup {}
    }
}

impl Zero for TrivialGroup {
    fn zero() -> Self {
        TrivialGroup::identity()
    }
    fn is_zero(&self) -> bool {
        true
    }
}

impl Add for TrivialGroup {
    type Output = TrivialGroup;
    fn add(self, _other: TrivialGroup) -> Self::Output {
        self
    }
}

impl Neg for TrivialGroup {
    type Output = TrivialGroup;
    fn neg(self) -> TrivialGroup {
        self
    }
}

impl AddAssign for TrivialGroup {
    fn add_assign(&mut self, _other : TrivialGroup) {
    }
}

impl SubAssign for TrivialGroup {
    fn sub_assign(&mut self, _other :TrivialGroup) {
    }
}

It seems like there are only three things I'm defining: the "add" operator, the "negate" operator, and the "zero" element, but I still have to manually implement 8 Traits on top of everything that alga_derive derives? Is there really no macro that does the obvious derivations of the 5 redundant traits?

@sebcrozet
Copy link
Member

sebcrozet commented Feb 18, 2019

@jeremysalwen That's correct. We only have macros for implementing the Abstract* traits currently. Though adding macros for the non-Abstract traits would definitely be a great addition.

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

No branches or pull requests

3 participants