Implementing flatMap () for state transition
Exercise 6.8, Chiusano and Bjarnason, Functional Programming in Scala, p. 87 asks how flatMap () can be implemented for the following trait:
trait RNG {
def nextInt: (Int, RNG)
}
type Rand[+A] = RNG => (A, RNG)
The answer key gives the following solution:
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
}
Stackoverflow provides many answers to flatMap () / monad questions, but none of them answered my questions regarding the next line of code for me.
I don't understand the syntax of the line
g(a)(r1)
(1) I don't understand how g (a) (r1) is evaluated. What syntactic function does (r1) serve? The string doesn't illustrate currying, I don't believe it, since g only takes one argument: A. (2) If g (a) already returns type Rand [B], then why doesn't the string end here? (3) What is the relationship between Rand [B] returned by g (a) and the second set of parentheses: (r1)? (4) if the return type of this implementation of flatMap () is Rand [B], which is RNG => (A, RNG), how are the parentheses to the right of the arrow enclosed? If I had to guess, I would say they are generated by the score (r1), but I don't really understand this code given my questions 1 through 3.
source to share
Remember that we are calling f
also g
inside the new anonymous function, as shown in the line
rng => { ... }
g
returns a Rand[B]
when given A
, so g(a)
evaluates the function from RNG
to (A, RNG)
.
So, g(a)
returns a function expecting as an argument RNG
, we can call this with ours r1
, which is of type RNG
.
Call result (B, RNG)
. Now, since the signature flatMap
expects you to return Rand[B]
which is the same as RNG => (B, RNG)
, and return (B, RNG)
inside our function, it matches the signature exactly.
source to share