lubeck 0.0.0-prealpha.5-abandoned

Functional programming framework written in cutting edge rust
Documentation
use crate::traits::{GenType, Monoid};

pub struct Writer<'a, W, A>
where
    W: Monoid,
{
    pub(crate) run_writer: Option<Box<dyn FnOnce(W) -> (A, W) + 'a>>,
}

impl<'a, W, A> Writer<'a, W, A>
where
    W: Monoid + 'a,
    A: 'a,
{
    pub fn new((a, wt): (A, W)) -> Self {
        Self {
            run_writer: Some(Box::new(move |w| (a, w.mappend(wt)))),
        }
    }

    pub fn eval_writer(self, w: W) -> A {
        self.run_writer
            .map(|writer| writer(w))
            .map(|(a, _)| a)
            .expect("Writer never empty")
    }

    pub fn run_with(self, w: W) -> (A, W) {
        self.run_writer
            .map(|writer| writer(w))
            .expect("Writer never empty")
    }

    pub fn exec_writer(self, w: W) -> W {
        self.run_writer
            .map(|writer| writer(w))
            .map(|(_, w)| w)
            .expect("Writer never empty")
    }

    pub fn run(self) -> (A, W) {
        self.run_writer
            .map(|writer_f| writer_f(W::mempty()))
            .expect("Writer never empty")
    }

    pub fn map_writer<F, B, V>(self, f: F) -> Writer<'a, V, B>
    where
        F: FnOnce((A, W)) -> (B, V) + 'a,
        V: Monoid,
    {
        Writer {
            run_writer: Some(Box::new(move |v: V| {
                let (a, w) = self.run();
                let (b, vt) = f((a, w));
                (b, v.mappend(vt))
            })),
        }
    }
}

impl<'a, W, A> GenType for Writer<'a, W, A>
where
    W: Monoid + 'a,
    A: 'a,
{
    type Type<B> = Writer<'a, W, B>;
}