2017-06-06 54 views
3

练习6.8,Chiusano和Bjarnason,Scala中的函数式编程, 87问一个人如何可能会为以下特征实现flatMap():用于状态转换的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 
} 

#2提供了许多答案flatMap()/单子的问题,但没有对于我回答关于下一行代码的问题。

我不理解的线

g(a)(r1) 

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

回答

3

请记住,我们呼吁fg里面新匿名函数,由线

rng => { ... } 

g所指示给出的A时,所以g(a)计算结果为函数从RNG(A, RNG)返回Rand[B]

所以g(a)返回一个函数期待一个RNG作为它的参数,我们可以用我们的r1,这是RNG类型的调用它。

该调用的结果是(B, RNG)。现在由于flatMap签名期望您返回与RNG => (B, RNG)相同的Rand[B],并且我们在函数中返回(B, RNG),它完全匹配签名。

+1

谢谢,卢卡,这太棒了。非常有意义。对我来说关键的知识是要知道(r1)确实代表对g(a)返回的函数的调用。我想这就像咖喱语法:f [A,B,C](a)(b):a =>(b => c),反过来。 –