1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
105
106
107
pub struct State<S, A> {
  pub(crate) run_f: Box<dyn FnOnce(S) -> (A, S)>,
}

impl<S: 'static, A: 'static> State<S, A> {
  pub fn unit(a: A) -> State<S, A> {
    Self::new(|s| (a, s))
  }

  pub fn new<T, B, F>(f: F) -> State<T, B>
  where
    F: FnOnce(T) -> (B, T) + 'static, {
    State { run_f: Box::new(f) }
  }

  pub fn run(self, s: S) -> (A, S) {
    (self.run_f)(s)
  }

  pub fn pure<T, B>(b: B) -> State<T, B>
  where
    B: Clone + 'static, {
    Self::new(move |s| (b.clone(), s))
  }

  pub fn fmap<B, F>(self, f: F) -> State<S, B>
  where
    F: FnOnce(A) -> B + 'static,
    B: Clone + 'static, {
    self.bind(move |a| Self::pure(f(a)))
  }

  pub fn fmap2<B, C, F>(self, sb: State<S, B>, f: F) -> State<S, C>
  where
    F: FnOnce(A, B) -> C + 'static,
    A: Clone,
    B: Clone + 'static,
    C: Clone + 'static, {
    self.bind(move |a| sb.fmap(move |b| f(a.clone(), b.clone())))
  }

  pub fn bind<B, F>(self, f: F) -> State<S, B>
  where
    F: FnOnce(A) -> State<S, B> + 'static,
    B: Clone + 'static, {
    Self::new(move |s| {
      let (a, s1) = self.run(s);
      f(a).run(s1)
    })
  }

  pub fn modify<T, F>(f: F) -> State<T, ()>
  where
    F: FnOnce(T) -> T + 'static,
    T: Clone + 'static, {
    let s = Self::get();
    s.bind(move |t: T| Self::set(f(t)))
  }

  pub fn get<T>() -> State<T, T>
  where
    T: Clone, {
    Self::new(move |t: T| (t.clone(), t))
  }

  pub fn set<T>(t: T) -> State<T, ()>
  where
    T: Clone + 'static, {
    Self::new(move |_| ((), t.clone()))
  }

  pub fn sequence(sas: Vec<State<S, A>>) -> State<S, Vec<A>> {
    Self::new(move |s| {
      let mut s_ = s;
      let actions = sas;
      let mut acc: Vec<A> = vec![];
      for x in actions.into_iter() {
        let (a, s2) = x.run(s_);
        s_ = s2;
        acc.push(a);
      }
      (acc, s_)
    })
  }
}

impl<S, A> Default for State<S, A>
where
  S: Default + 'static,
  A: Default + 'static,
{
  fn default() -> Self {
    Self::new(|_| (A::default(), S::default()))
  }
}

#[cfg(test)]
mod tests {
  use super::*;

  #[test]
  fn state() {
    let s = State::<i32, i32>::pure(10);
    let r = s.run(10);
    println!("{:?}", r);
  }
}