PhotonQuantum / magic-in-ten-mins-rs

十分钟魔法练习 in Rust
Creative Commons Attribution 4.0 International
436 stars 20 forks source link

I don’t understand some parts of StateMonad #1

Open cangSDARM opened 3 years ago

cangSDARM commented 3 years ago

in fib section:

fn pure(v: A) -> Self // pure: (v) -> State<InState, v>
fn flatMap<F> // F: Fn(A) -> State<InState, B>

fn fib(n: u64) -> State<'static, (u64, u64), u64> {
        match n {
            0 => State::flatMap(
                get(),
                |x: (u64, u64)| { State::pure(x.0) }    /// <--- here, 难道不应该是 |x: u64| { State::pure(x) } 么?
            ),
            _ => State::flatMap(
                modify(|x: (u64, u64)| { (x.1, x.0 + x.1) }),  /// 这里就很明显,说明 value 是 u64, state 是 (u64, u64)
                move |_| fib(n - 1)
         )
    }
}

and later part:

assert_eq!(fib(7).eval((0, 1)), 13);   /// 这里修改为 eval((2, 3)), 它会执行 2...7 的fib么
fzyzcjy commented 2 years ago

// 这里修改为 eval((2, 3)), 它会执行 2...7 的fib么

I guess no. At least fib(7) means it will include fib(6), fib(5), ... fib(0).

But it may give 9th fib number?

PhotonQuantum commented 2 years ago

Sorry for my extremely late reply!

            0 => State::flatMap(
                get(),
                |x: (u64, u64)| { State::pure(x.0) }    /// <--- here, 难道不应该是 |x: u64| { State::pure(x) } 么?
            ),

Let's look at the implementation of get.

pub fn get<'a, S: Clone>() -> State<'a, S, S> {
    State { run_state: Box::new(|state: S| (state.clone(), state)) }
}

The idea of get is to copy the state to the output field, so we may work on it or just return it (or say, pure it, if you like). As the state is of type (int, int), the output field is of the same type now. So, when we flatMap on it, we are coping with a (int, int) input.

assert_eq!(fib(7).eval((0, 1)), 13);   /// 这里修改为 eval((2, 3)), 它会执行 2...7 的fib么

The fib sequence starts with 0, 1. If you change the initial state to 2, 3, you have a sequence like 2, 3, 5, 8, 13, 21, 34, 55, ... . So you get the 8th num in this sequence, which is 55, although you may say that it's the 11th fib number as well.

Note: the fib seq here starts from 0 and 1, and fib(n) means the (n+1)-th fib number because we index from 0.