我通过阅读Scala 中的函数式编程(又名红皮书)这本书来学习函数式编程,并且我遇到了我的第一个真正的障碍。在第6章中,本书使用随机数生成器的示例来说明如何使用副作用来改变状态。然后,本书继续演示您通常会遇到的模式,以及在制作功能性有状态 api 时可能会采取的一些切线。当我试图理解以下代码时,我的问题出现了:
type Rand[+A] = RNG => (A, RNG)
def map[A, B](s: Rand[A])(f: A => B): Rand[B] =
rng => {
val (nxt, nxtrng) = s(rng)
(f(nxt), nxtrng)
}
def nonNegativeLessThan(n: Int): Rand[Int] =
map(nonNegativeIntv2) { i =>
val mod = i % n
if (i + (n - 1) - mod >= 0) mod else nonNegativeLessThan(n)(???)
}
我希望这是足够的上下文来了解代码的作用。这直接来自第 86 页的书。方法 nonNegativeLessThan 的 if 语句如何过滤掉大于 32 位整数中 n 的最大倍数的 i 值? else 子句中的递归调用不是返回Rand[Int] 类型的值吗?一般来说,我对粗体代码中发生的事情感到困惑。这是一本非常好的书,所以我对到目前为止的进展感到满意,并且我觉得我学到了很多关于函数式编程的知识。如果这个问题格式不正确并且格式存在问题,我深表歉意。这是我关于堆栈溢出的第一篇文章!感谢那些看到这篇文章的人,我希望它对遇到同样问题的人有所帮助。
最佳答案
How does the if statement for method nonNegativeLessThan filters out values of i that are greater than the largest multiple of n in a 32 bit integer?
如果i
大于n
的最大倍数,则i + (n - 1) - mod
将溢出并产生负数。随后的 >= 0
则为 false。
Doesn't the recursive call in the else clause return a value of type Rand[Int]?
嗯,nonNegativeLessThan(n)
确实是 Rand[Int]
类型。然而它说的是 nonNegativeLessThan(n)(???)
,也就是说,它将 nonNegativeLessThan
应用于 n
,然后应用结果值(类型为 Rand[Int]
,这是一种函数类型)到 ???
,并生成一个 Int
。或者更确切地说,如果 ???
曾经产生过真正的值(value),它就会这样做,但事实并非如此。
这里的问题是您必须传递 RNG 的状态而不是 ???
,但是 map
函数不允许您访问该状态。您需要 flatMap
来解决这个问题 - 这大概就是本书接下来要讨论的内容。
关于scala - 如何使有状态 API 变得纯粹,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/70644838/