use crate::op::Operator;
use super::{AbelianGroup, Field, Ring};
pub trait Module<Oa: Operator, Om: Operator>: AbelianGroup<Oa> {
type Scalar: Ring<Oa, Om>;
fn scale(s: &Self::Scalar, v: Self) -> Self;
}
pub trait VectorSpace<Oa: Operator, Om: Operator>: Module<Oa, Om>
where
Self::Scalar: Field<Oa, Om>,
{
}
pub trait FreeModule<Oa: Operator, Om: Operator>: Module<Oa, Om> {
fn rank() -> usize;
fn basis_element(_i: usize) -> Self;
fn coordinate(&self, i: usize) -> Self::Scalar;
}
pub trait LinearMap<Oa: Operator, Om: Operator>
where
<Self::Domain as Module<Oa, Om>>::Scalar: Field<Oa, Om>,
{
type Domain: VectorSpace<Oa, Om>;
type Codomain: VectorSpace<Oa, Om, Scalar = <Self::Domain as Module<Oa, Om>>::Scalar>;
fn apply(&self, v: &Self::Domain) -> Self::Codomain;
}