I am working through the red book and when checking my answers for the exercises , I found that the solution for one of the exercises (6.11) was quite different (and much more elegant and cryptic than my own solution).
Here is the code:
object Candy {
def update: Input => Machine => Machine = (i: Input) => (s: Machine) =>
(i, s) match {
case (_, Machine(_, 0, _)) => s
case (Coin, Machine(false, _, _)) => s
case (Turn, Machine(true, _, _)) => s
case (Coin, Machine(true, candy, coin)) =>
Machine(false, candy, coin + 1)
case (Turn, Machine(false, candy, coin)) =>
Machine(true, candy - 1, coin)
}
def simulateMachine(inputs: List[Input]): State[Machine, (Int, Int)] = for {
_ <- State.sequence(inputs map (modify[Machine] _ compose update))
s <- get
} yield (s.coins, s.candies)
def modify[S](f: S => S): State[S, Unit] = for {
s <- get // Gets the current state and assigns it to `s`.
_ <- set(f(s)) // Sets the new state to `f` applied to `s`.
} yield ()
def get[S]: State[S, S] = State(s => (s, s))
def set[S](s: S): State[S, Unit] = State(_ => ((), s))
The bit I am unsure of is this line:
inputs map (modify[Machine] _ compose update)
I understand how compose works but this particular syntax is really throwing me for a loop. Is there a way that this can be rewritten that is not so compact that would help a noob understand?
Thanks in advance.
Also for anyone else trying to better understand how this code works, this post I found helpful.