纯功能随机数字发生器 - 状态monad [英] Pure functional Random number generator - State monad

查看:126
本文介绍了纯功能随机数字发生器 - 状态monad的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

Scala中的 函数式编程 '演示了一个纯函数随机数生成器的例子,如下所示:

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






这个用法看起来像

  val(randomNumber,nextState)= rng.nextInt 

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



如果有另外一个函数来解除 seed RNG ?如果是这样,那么我们如何期望这个API的客户端知道它(因为在非功能实现中,用户只需调用 nextInt 并且状态由API维护)



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

RNG 是纯粹的函数,对于相同的输入,你总是得到相同的输出。非纯功能的部分留给该API的用户使用 RNG 以纯功能的方式,你必须初始化它始终使用相同的初始值,但是你总是会得到相同的数字序列,这是没有用的。



<否则,你将不得不依赖初始化 RNG 到外部系统(通常是挂钟时间),因此引入副作用(再见纯函数)。 / p>

  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.s (System.currentTimeMillis)))((st,_)=> st._2.nextInt)
.tail
.map(_._ 1)

println(randoms.take(5).toList)
println(randoms。过滤器(_> 0).take(3).toList)


The book 'Functional Programming in Scala' demonstrates an example of pure functional random number generator as below

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))
        }
    }
}

The usage will look like

val (randomNumber,nextState) = rng.nextInt

I do get the part that it's a pure function as it returns the next state and leaves it on the API client to use it to call nextInt the next time it would need a random number but what I did not understand is 'how will the first random number be generated as we must provide seed at least once.

Should there be another function to lift seed to get a RNG? And if so then how do we expect the client of this API to know about it (because in the non-functional implementation user just calls nextInt and the state is maintained by API)

Can someone give a full example of pure functional random number generator in Scala and perhaps relate it to state Monad in general.

解决方案

That random generator RNG is pure functional, for the same inputs you get always the same outputs. The non-pure-functional part is left for the user of that API (you).

To use the RNG in a pure-functional way you have to initialize it always with the same initial value, but then you will always get the same sequence of numbers, which is not so useful.

Otherwise, you will have to rely the initialization of RNG to an external system (usually the wall-clock time) and so introducing side effects (bye pure functional).

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)


[EDIT]

Inspired by the answer of @Aivean, I created my version of 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)

这篇关于纯功能随机数字发生器 - 状态monad的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆