use crate::prelude::GenType;
pub struct State<'a, S, A> {
pub(crate) run_state: Option<Box<dyn FnOnce(S) -> (A, S) + 'a>>,
}
impl<'a, S, A> State<'a, S, A>
where
S: Clone + 'a,
A: 'a,
{
pub fn new<F>(f: F) -> Self
where
F: FnOnce(S) -> (A, S) + 'a,
{
Self {
run_state: Some(Box::new(f)),
}
}
pub fn put(self, state: S) -> State<'a, S, ()> {
State {
run_state: Some(Box::new(move |_| ((), state))),
}
}
pub fn get(self) -> State<'a, S, S> {
let state_f = move |s| {
let (_, s) = self.run(s);
(s.clone(), s)
};
State {
run_state: Some(Box::new(state_f)),
}
}
pub fn modify<F>(self, f: F) -> Self
where
F: FnOnce(S) -> S + 'a,
{
let state_f = move |s| {
let (a, s) = self.run(s);
(a, f(s))
};
Self {
run_state: Some(Box::new(state_f)),
}
}
pub fn run(self, s: S) -> (A, S) {
self.run_state
.map(move |f| f(s))
.expect("State has inner func")
}
}
impl<'a, S, A> GenType for State<'a, S, A>
where
S: Clone + 'a,
A: 'a,
{
type Type<B> = State<'a, S, B>;
}