Реализация flatMap() для перехода между состояниями

Упражнение 6.8, Кьюзано и Бьярнасон, Функциональное программирование в Scala, с. 87 спрашивает, как можно реализовать flatMap() для следующей черты:

trait RNG {
  def nextInt: (Int, RNG)
}

type Rand[+A] = RNG => (A, RNG)

Ключ ответа дает следующее решение:

def flatMap[A,B](f: Rand[A])(g: A => Rand[B]): Rand[B] =
rng => {
  val (a, r1) = f(rng)
  g(a)(r1) // We pass the new state along
}

Stackru предоставляет много ответов на вопросы flatMap()/monad, но ни один из них для меня не ответил на мои вопросы, касающиеся следующей или последней строки кода.

Я не понимаю синтаксис строки

g(a)(r1)

(1) Я не понимаю, как оценивает g(a)(r1). Какой синтаксической функции служит (r1)? Строка не является примером каррирования, я не верю, поскольку g принимает только один аргумент: A. (2) Если g (a) уже вернет тип Rand[B], то почему строка здесь не заканчивается? (3) какова связь между Rand[B], возвращаемым g (a), и вторым набором скобок: (r1)? (4) если возвращаемым типом этой реализации flatMap() является Rand[B], который равен RNG => (A, RNG), как генерируются закрывающие скобки справа от стрелки? Если бы мне пришлось угадывать, я бы сказал, что они генерируются оценкой (r1), но я не совсем понимаю этот код, учитывая мои вопросы с 1 по 3.

1 ответ

Решение

Помните, что мы звоним f а также g внутри новой анонимной функции, как указано в строке

rng => { ... }

g возвращает Rand[B] когда дали A, так g(a) оценивает функцию от RNG в (A, RNG),

Так g(a) возвращает функцию, ожидающую RNG в качестве аргумента, мы можем назвать это с нашими r1, который имеет тип RNG,

Результат звонка (B, RNG), Теперь, так как flatMap подпись ожидает от вас возврата Rand[B] который так же, как RNG => (B, RNG) и мы вернемся (B, RNG) внутри нашей функции он точно соответствует сигнатуре.

Другие вопросы по тегам