gpt4 book ai didi

scala - 纯函数随机数生成器 - 状态单子(monad)

转载 作者:行者123 更新时间:2023-12-03 00:29:00 29 4
gpt4 key购买 nike

《Scala 函数式编程》一书演示了纯函数式随机数生成器的示例,如下所示

trait RNG {
def nextInt: (Int, RNG)
}

object RNG {
def simple(seed: Long): RNG = new RNG {
def nextInt = {
val seed2 = (seed*0x5DEECE66DL + 0xBL) &
((1L << 48) - 1)
((seed2 >>> 16).asInstanceOf[Int],
simple(seed2))
}
}
}

用法如下

val (randomNumber,nextState) = rng.nextInt

我确实明白它是一个纯函数,因为它返回下一个状态并将其保留在 API 客户端上,以便下次使用它调用 nextInt需要一个随机数,但我不明白的是“如何生成第一个随机数,因为我们必须至少提供一次种子

是否应该有另一个函数来提升种子以获得RNG?如果是这样,那么我们如何期望这个 API 的客户端知道它(因为在非功能性实现中,用户只需调用 nextInt 并且状态由 API 维护)

有人可以给出 Scala 中纯函数随机数生成器的完整示例,并可能将其与一般状态 Monad 联系起来。

最佳答案

随机生成器RNG是纯函数式的,对于相同的输入,你总是得到相同的输出。非纯功能部分留给该 API 的用户(您)。

要以纯函数方式使用RNG,您必须始终使用相同的初始值对其进行初始化,但随后您将始终获得相同的数字序列,这不太有用。

否则,您将不得不依赖外部系统(通常是挂钟时间)来初始化 RNG,从而引入副作用(再见纯函数式)。

val state0 = RNG.simple(System.currentTimeMillis)

val (rnd1, state1) = state0.nextInt
val (rnd2, state2) = state1.nextInt
val (rnd3, state3) = state2.nextInt

println(rnd1, rnd2, rnd3)
<小时/>

[编辑]

受到@Aivean的回答的启发,我创建了我的随机版本Stream:

def randoms: Stream[Int] = Stream.from(0)
.scanLeft((0, RNG.simple(System.currentTimeMillis)))((st, _) => st._2.nextInt)
.tail
.map(_._1)

println(randoms.take(5).toList)
println(randoms.filter(_ > 0).take(3).toList)

关于scala - 纯函数随机数生成器 - 状态单子(monad),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/31818787/

29 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com