2

I'm having a hard time breaking down the evaluation in Section 6.9 when implementing map2 in terms of FlatMap from Functional Programming in Scala.

So map2 looks like

def map2[A,B,C](ra: Rand[A], rb: Rand[B])(f: (A, B) => C): Rand[C] = {
  rng => {
    val (a, r1) = ra(rng)
    val (b, r2) = rb(r1)
    (f(a, b), r2)
  }
}

and flatMap looks like:

def flatMap[A, B](f: Rand[A])(g: A => Rand[B]): Rand[B] = rng => {
  val (a, r1) = f(rng)
  g(a)(r1)
}

I beat my head against a wall for a few days and could not figure out how to do map2 in terms of flatmap (map, oddly, came to me right away).

Looking at a solution to map2 in terms of flatMap from the solutions repo:

def _map2[A,B,C](s1: Rand[A], s2: Rand[B])(f: (A, B) => C): Rand[C] = {
  flatMap(s1)(a => flatMap(s2)(b => unit(f(a,b))))
}

But I'm confused on how this function expands in terms of evaluation --I can't seem to write out the evaluation by hand. I don't see how I have the second f: (A, B) => C that gets returned to the outer flatMap.

I suppose this is the next question after this post: Implementation of flatMap() for State transition !

mat4nier
  • 262
  • 4
  • 14
  • 1
    For `Rand` to work, the input seed must be "incremented" for each pseudo-random value generated. If the same seed is used twice to pull two `X`s out of a `Rand[X]`, those two `X`s will be the same. The "effect" of the `Rand` monad is "incrementing" this seed for you. `map2` takes three arguments: `Rand[A]`, `Rand[B]` and a function `(A,B) -> C`. `map2` must generate the pseudo-random `A` and `B` before the function `(A,B)->C` can be applied. `map2` generates the `A`, increments the seed, then generates the `B`, increments the seed, and then applies the function `(A, B) -> C`. – Peter Becich Aug 29 '17 at 03:16
  • 1
    100%. It's clear in the original implementation of map2. I don't see how scala expands the `_map2` function that uses flatMap. I suppose this is more of a question of how Scala would evaluate the above. If I go inside out, it looks like f(a,b) is expanded first but it's not clear since a and b have not been generated yet. It's not clear to me which of the two `flatMap` even is the first to increment the seed and pass the state. – mat4nier Aug 29 '17 at 03:50
  • 1
    Okay, I think I understand now, thanks. Take a look at these: https://github.com/peterbecich/fpinscala/blob/master/answers/src/main/scala/fpinscala/state/State.scala#L20-L27 and https://github.com/peterbecich/fpinscala/blob/master/answers/src/main/scala/fpinscala/state/State.scala#L181-L200 – Peter Becich Aug 29 '17 at 04:51
  • 1
    It's a bogus implementation of the `RNG` trait that only increments the seed by one. – Peter Becich Aug 29 '17 at 04:52
  • Ah. AH! Thank you. This was the breakthrough I've been trying to see all day. – mat4nier Aug 29 '17 at 05:14
  • Cool! Sure thing! – Peter Becich Aug 29 '17 at 16:05

0 Answers0