代数 - 作用 - 代入作用

代入を表現する 作用を定義する.

集合 \(X\) について,

\[A_X = X \sqcup \{ \bot \}\]

は, 代入(または値の上書き)をする作用 \((\ast)\) を表現する.

Min/Max モノイド と組み合わせてモノイド作用付きモノイドとしたとき, これを 遅延セグメントツリー に載せると, 区間更新の出来る RMQ になる.

/// Algebra - Assign Monoidal Act
use crate::algebra::act::*;
use crate::algebra::monoid::*;
use crate::monoid; // IGNORE

#[derive(Debug, Clone, Copy)]
pub enum Assign<X> {
    Some(X),
    None,
}
monoid! {
    Assign<X> where [X];
    one = Assign::None;
    mul(self, other) = {
        match (self, &other) {
            (x, Assign::None) => x,
            _ => other,
        }
    }
}
impl<X: Copy> Act<X> for Assign<X> {
    fn act(&self, other: X) -> X {
        match *self {
            Assign::None => other,
            Assign::Some(x) => x,
        }
    }
}

#[cfg(test)]
mod test_act_assign {
    use crate::algebra::act_assign::*;
    #[test]
    fn it_works() {
        assert_eq!(Assign::Some(1).act(0), 1);
        assert_eq!(Assign::None.act(0), 0);
        assert_eq!((Assign::Some(1) * Assign::Some(2)).act(0), 2);
        assert_eq!((Assign::None * Assign::Some(2)).act(0), 2);
        assert_eq!((Assign::Some(1) * Assign::None).act(0), 1);
        assert_eq!((Assign::None * Assign::None).act(0), 0);
        assert_eq!((Assign::None * Assign::None * Assign::Some(9)).act(0), 9);
    }
}