繁体   English   中英

纯函数随机数发生器 - 状态monad

[英]Pure functional Random number generator - State monad

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但我不明白的是' 第一个怎么样生成随机数,因为我们必须至少提供一次seed

是否应该有其他功能来提升seed以获得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答案的启发,我创建了我的版本的randoms 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流结合:

  def randStream(r: RNG): Stream[Int] = r.nextInt match {
    case (value, next) => value #:: randStream(next)
  }

  val rng = randStream(RNG.simple(123))
  println(rng.take(10).toList)
  println(rng.take(5).toList)

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

一个纯功能的RNG。

val state0 = RNG.simple(1234)
val (r1, state1) = state0.nextInt
val (r2, state2) = state1.nextInt
// etc.
val (x, _) = state1.nextInt
assert (x == r2)

递归函数,源自基于@Aivean Stream的函数,

def rand(n: Int, r: RNG): List[Int] = { 
  if (n < 0) List() 
  else {
    val (value, next) = r.nextInt
    value :: rand(n-1, next) 
  }
}

要获得5随机值,

rand(5, RNG.simple(System.currentTimeMillis) )

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM