pub trait DelegateRing: PartialEq {
type Base: ?Sized + RingBase;
type Element;
// Required methods
fn get_delegate(&self) -> &Self::Base;
fn delegate_ref<'a>(
&self,
el: &'a Self::Element,
) -> &'a <Self::Base as RingBase>::Element;
fn delegate_mut<'a>(
&self,
el: &'a mut Self::Element,
) -> &'a mut <Self::Base as RingBase>::Element;
fn delegate(&self, el: Self::Element) -> <Self::Base as RingBase>::Element;
fn rev_delegate(
&self,
el: <Self::Base as RingBase>::Element,
) -> Self::Element;
// Provided methods
fn postprocess_delegate_mut(&self, el: &mut Self::Element) { ... }
fn element_cast(&self, el: Self::Element) -> <Self as RingBase>::Element { ... }
fn rev_element_cast(&self, el: <Self as RingBase>::Element) -> Self::Element { ... }
fn rev_element_cast_ref<'a>(
&self,
el: &'a <Self as RingBase>::Element,
) -> &'a Self::Element { ... }
}Expand description
Trait to simplify implementing newtype-pattern for rings.
When you want to create a ring that just wraps another ring,
possibly adding some functionality, you can implement DelegateRing
instead of RingBase, and just provide how to map elements in the new
ring to the wrapped ring and vice versa.
§Conditional Implementations
Some special ring traits (e.g. DivisibilityRing) are immediately implemented
for R: DelegateRing as soon as R::Base: SpecialRingTrait. However, this
of course prevents any implementation fo DelegateRing to provide a custom
implementation (except for specialization in some cases), due to conflicting
trait impls. Hence, for other traits, we use marker traits to mark an implementation
R of DelegateRing to also automatically implement a special ring trait as soon
as R::Base: SpecialRingTrait. These cases are currently
DelegateRingImplFiniteRingfor automatic implementations ofFiniteRingandFiniteRingSpecializable.DelegateRingImplEuclideanRingfor automatic implementations ofPrincipalIdealRingandEuclideanRing
§Example
#[derive(PartialEq, Clone)]
struct MyI32Ring;
struct MyI32RingEl(i32);
impl DelegateRing for MyI32Ring {
type Base = StaticRingBase<i32>;
type Element = MyI32RingEl;
fn get_delegate(&self) -> &Self::Base {
StaticRing::<i32>::RING.get_ring()
}
fn delegate_ref<'a>(&self, MyI32RingEl(el): &'a MyI32RingEl) -> &'a i32 {
el
}
fn delegate_mut<'a>(&self, MyI32RingEl(el): &'a mut MyI32RingEl) -> &'a mut i32 {
el
}
fn delegate(&self, MyI32RingEl(el): MyI32RingEl) -> i32 {
el
}
fn postprocess_delegate_mut(&self, _: &mut MyI32RingEl) {
// sometimes it might be necessary to fix some data of `Self::Element`
// if the underlying `Self::Base::Element` was modified via `delegate_mut()`;
// this is not the case here, so leave empty
}
fn rev_delegate(&self, el: i32) -> MyI32RingEl {
MyI32RingEl(el)
}
}
// you will have to implement `CanIsoFromTo<Self>`
impl_eq_based_self_iso!{ MyI32Ring }
let ring = RingValue::from(MyI32Ring);
assert_el_eq!(ring, ring.int_hom().map(1), ring.one());An example when special ring traits are automatically implemented is given by the following.
struct BoringRingWrapper<R>(R);
impl<R> PartialEq for BoringRingWrapper<R>
where R: RingStore
{
fn eq(&self, other: &Self) -> bool {
self.0.get_ring() == other.0.get_ring()
}
}
impl<R> DelegateRing for BoringRingWrapper<R>
where R: RingStore
{
type Base = R::Type;
type Element = El<R>;
fn get_delegate(&self) -> &Self::Base {
self.0.get_ring()
}
fn delegate(&self, el: Self::Element) -> <Self::Base as RingBase>::Element { el }
fn delegate_mut<'a>(&self, el: &'a mut Self::Element) -> &'a mut <Self::Base as RingBase>::Element { el }
fn delegate_ref<'a>(&self, el: &'a Self::Element) -> &'a <Self::Base as RingBase>::Element { el }
fn rev_delegate(&self, el: <Self::Base as RingBase>::Element) -> Self::Element { el }
}DivisibilityRing is automatically implemented (but can be specialized):
fn divide_in_wrapped_ring<R>(base_ring: R)
where R: RingStore,
R::Type: DivisibilityRing
{
let wrapped_ring = BoringRingWrapper(base_ring);
assert!(wrapped_ring.checked_div(&wrapped_ring.one(), &wrapped_ring.one()).is_some());
}FiniteRing for example is not automatically implemented:
fn size_of_wrapped_ring<R>(base_ring: R)
where R: RingStore,
R::Type: FiniteRing
{
let wrapped_ring = BoringRingWrapper(base_ring);
assert!(wrapped_ring.size(BigIntRing::RING).is_some());
}But we can add a delegate-implementation of FiniteRing by adding the marker trait DelegateRingImplFiniteRing:
impl<R> DelegateRingImplFiniteRing for BoringRingWrapper<R>
where R: RingStore
{}
fn size_of_wrapped_ring<R>(base_ring: R)
where R: RingStore,
R::Type: FiniteRing
{
let wrapped_ring = BoringRingWrapper(base_ring);
assert!(wrapped_ring.size(BigIntRing::RING).is_some());
}Required Associated Types§
Required Methods§
fn get_delegate(&self) -> &Self::Base
fn delegate_ref<'a>( &self, el: &'a Self::Element, ) -> &'a <Self::Base as RingBase>::Element
fn delegate_mut<'a>( &self, el: &'a mut Self::Element, ) -> &'a mut <Self::Base as RingBase>::Element
fn delegate(&self, el: Self::Element) -> <Self::Base as RingBase>::Element
fn rev_delegate(&self, el: <Self::Base as RingBase>::Element) -> Self::Element
Provided Methods§
fn postprocess_delegate_mut(&self, el: &mut Self::Element)
Sourcefn element_cast(&self, el: Self::Element) -> <Self as RingBase>::Element
fn element_cast(&self, el: Self::Element) -> <Self as RingBase>::Element
Necessary in some locations to satisfy the type system
Sourcefn rev_element_cast(&self, el: <Self as RingBase>::Element) -> Self::Element
fn rev_element_cast(&self, el: <Self as RingBase>::Element) -> Self::Element
Necessary in some locations to satisfy the type system
Sourcefn rev_element_cast_ref<'a>(
&self,
el: &'a <Self as RingBase>::Element,
) -> &'a Self::Element
fn rev_element_cast_ref<'a>( &self, el: &'a <Self as RingBase>::Element, ) -> &'a Self::Element
Necessary in some locations to satisfy the type system
Dyn Compatibility§
This trait is not dyn compatible.
In older versions of Rust, dyn compatibility was called "object safety", so this trait is not object safe.