Код здесь: https://github.com/fpinscala/fpinscala/blob/master/answers/src/main/scala/fpinscala/state/State.scala
def simulateMachine(inputs: List[Input]): State[Machine, (Int, Int)] = for {
_ <- sequence(inputs map ((modify[Machine] _) compose update))
s <- get
} yield (s.coins, s.candies)
Я не понимаю, как вторая строка s <- get
работает в этом для понимания.
Насколько я вижу, в первой строке создается State [Machine, List [Unit]], а flatMap выбрасывает List [Unit] с _.
Впоследствии во второйСтрока, я не понимаю, как get
применяется к Machine
, созданному в первой строке. Как проходит Machine
?
РЕДАКТИРОВАТЬ: Спасибо jwvh и Маркусу Аппелю за ответы, теперь я понимаю, что get
- это метод без параметров, который возвращает State[S, S]
.
Теперь я думаю, что понял, но, пожалуйста, поправьте меня, если я ошибаюсь. Во-первых, я расширил понимание, как показано ниже.
sequence(inputs map ((modify[Machine] _) compose update))
.flatMap(_ => get
.map(s => (s.coins, s.candies))
get.map(s => (s.coins, s.candies)
можно заменить на State(s => (s, s)).map(s => (s.coins, s.candies)
и в конечном итоге State(s => (s, (s.coins, s.candies)))
sequence(inputs map ((modify[Machine] _) compose update))
.flatMap(_ => State(s => (s, (s.coins, s.candies))))
Подставляя внешний sequence(inputs map ((modify[Machine] _) compose update)).flatMap
с определением, я вижу
State(s => {
val (a, s1) = sequence(inputs map ((modify[Machine] _) compose update)).run(s)
f(a).run(s1)
})
Теперь я заменяю f(a)
оценкой _ => State(s => (s, (s.coins, s.candies)))
State(s => {
val (a, s1) = sequence(inputs map ((modify[Machine] _) compose update)).run(s)
State(s => (s, (s.coins, s.candies))).run(s1)
})
По существу, sequence(inputs map ((modify[Machine] _) compose update))
производит Machine
в конечном состоянии после выполнения списка входов и производитвыход типа State[Machine, List[Unit]]
. Но фактическое Machine
в этом государстве явно не передается. Скорее, он передается неявно по определению flatMap
, когда он вызывает State(s => (s, (s.coins, s.candies))).run(s1)
через .run(s1)
.