代数 - モノイド
積に関するモノイド \((X, \times, 1)\) を定義する.
- 演算
std::ops::Mul
, - 単位元
Monoid::one()
Rust の i64
, f64
はそのまま乗算に関してモノイドになっている.
また, ユーザーが定義した型をモノイドにするためのマクロ monoid!
を提供する.
// monoid マクロの使用例
monoid! {
MyType ;
one = MyType(1) ;
mul(self, other) = { compute_multiplication(self, other) }
}
// 型パラメータを取る場合
monoid! {
MyType<X> where [ X:Ord ] ;
one = MyType(X::one) ;
mul(self, other) = { compute_multiplication(self, other) }
}
monoid!
は product()
, mul_assign()
を自動で定義する.
/// Algebra - Def of Monoid (*, 1)
pub trait Monoid: std::ops::Mul<Output = Self> + std::iter::Product
where
Self: std::marker::Sized,
{
fn one() -> Self;
}
#[macro_export]
macro_rules! monoid {
(
$type:ty where [ $( $params:tt )* ];
one = $one:expr;
mul($self:ident, $y:ident) = $code:block
$(;)*
) => {
impl<$($params)*> std::ops::Mul for $type {
type Output = Self;
fn mul($self, $y: Self) -> Self { $code }
}
impl<$($params)*> std::ops::MulAssign for $type where Self: Clone {
fn mul_assign(&mut $self, $y: Self) {
*$self = (*$self).clone() * $y;
}
}
impl<$($params)*> std::iter::Product for $type {
fn product<I: Iterator<Item = Self>>(iter: I) -> Self {
iter.fold(Self::one(), std::ops::Mul::mul)
}
}
impl<$($params)*> Monoid for $type {
fn one() -> Self { $one }
}
};
(
$type:ty;
one = $one:expr;
mul($self:ident, $y:ident) = $code:block
$(;)*
) => {
monoid! { $type where []; one = $one; mul($self, $y) = $code; }
};
}
impl Monoid for i64 {
fn one() -> Self {
1
}
}
impl Monoid for f64 {
fn one() -> Self {
1.0
}
}