用于状态转换的flatMap()的实现

时间:2017-06-06 19:16:49

标签: scala functional-programming monads state-monad flatmap

练习6.8,Chiusano和Bjarnason, Scala中的函数编程,p。 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
}

Stackoverflow为flatMap()/ monad问题提供了很多答案,但没有一个能够回答我关于下一行代码的问题。

我不明白该行的语法

g(a)(r1)

(1)我不明白g(a)(r1)是如何评价的。 (r1)提供了什么句法功能?这条线没有举例说明currying,我不相信,因为g只有一个参数:A。 (2)如果g(a)已经返回Rand [B]类型,那么为什么这条线不会在这里结束? (3)g(a)返回的Rand [B]与第二组括号之间的关系是什么:(r1)? (4)如果flatMap()的这个实现的返回类型是Rand [B],它等于RNG => (A,RNG),如何生成箭头右侧的括号?如果我不得不猜测我会说它们是由评估生成的(r1),但是我不明白这个代码给出了我的问题1到3.

1 个答案:

答案 0 :(得分:4)

请记住,我们在新的匿名函数中调用fg,如行所示

rng => { ... }

g在获得Rand[B]时会返回A,因此g(a)会评估从RNG(A, RNG)的函数。

因此g(a)会返回一个期望RNG作为参数的函数,然后我们可以使用类型为r1的{​​{1}}调用此函数。

通话结果为RNG。既然(B, RNG)签名要求您返回与flatMap相同的Rand[B]并且我们在函数内返回RNG => (B, RNG),那么它与签名完全匹配。