纯功能随机数字发生器 - 状态monad [英] Pure functional Random number generator - State monad
问题描述
Scala中的 函数式编程 '演示了一个纯函数随机数生成器的例子,如下所示:
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
以纯功能的方式,你必须初始化它始终使用相同的初始值,但是你总是会得到相同的数字序列,这是没有用的。 <否则,你将不得不依赖初始化
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屋!