Как это для понимания строит состояние при назначении подчеркивания?

Фон
Значение forExpression (ниже) возвращает монаду StateT, которая принимает в качестве параметра начальное состояние, добавляет к состоянию 2, а затем 3, а затем умножает это значение на 10.

Вопрос
Почему функции add(2) и add(3) выполняются при запуске этого экземпляра StateT после того, как результат этих двух функций "отбрасывается" путем присвоения ему символа подчеркивания?

Пример
если вы оцениваете forExpression с начальным состоянием IntState(1), почему возвращается IntState(60) вместо IntState(10)?

Ниже приведен минимальный фрагмент кода, или вы можете просмотреть полный исходный код на github.

Этот код был обнаружен при чтении книги Элвина Александера «Упрощенное функциональное программирование».

  case class IntState(i: Int)

  def add(i: Int) = StateT[IO, IntState, Int] { oldState =>
    val newValue = i + oldState.i
    val newState = oldState.copy(i = newValue)
    IO((newState, newValue))
  }

  def multiply(i: Int) = StateT[IO, IntState, Int] { oldState =>
    val newValue = i * oldState.i
    val newState = oldState.copy(i = newValue)
    IO((newState, newValue))
  }

  val forExpression: StateT[IO, IntState, Int] = for {
    _ <- add(2)
    _ <- add(3)
    x <- multiply(10)
  } yield x

person randbw    schedule 08.06.2018    source источник


Ответы (1)


Простое объяснение высокого уровня: StateT вычисления имеют отдельные состояние и результат (например, newState и newValue в IO((newState, newValue)) в вашем коде). Слева от <- появляется часть newValue, и только она игнорируется в _ <- .... Манипуляции с newState неявны и не отбрасываются.

Для низкого уровня вы можете:

  1. Переведите для понимания в flatMap.

  2. Расширьте определение flatMap StateT.

  3. Посмотрите, что происходит с состоянием в функции результата.

person Alexey Romanov    schedule 08.06.2018
comment
Спасибо за объяснение. Переведу for-comprehension в flatMap и посмотрим, поможет ли это! - person randbw; 08.06.2018