第一种方法是OK。 第二个不断重复相同的数字。
对我而言,这是非常模糊的......你能指出好的方向吗?
module Normal =
let rnd = new MersenneTwister()
let sampleNormal =
fun () -> let rec randomNormal() = let u1, u2 = rnd.NextDouble(),rnd.NextDouble()
let r, theta= sqrt (-2. * (log u1)), 2. * System.Math.PI * u2
seq { yield r * sin theta; yield r * cos theta ; printfn "next";yield! randomNormal() }
randomNormal()
let sampleNormalBAD =
fun () -> let rec randomNormal = let u1, u2 = rnd.NextDouble(),rnd.NextDouble()
let r, theta= sqrt (-2. * (log u1)), 2. * System.Math.PI * u2
seq { yield r * sin theta; yield r * cos theta ; printfn "next";yield! randomNormal }
randomNormal
Normal.sampleNormal() |> Seq.take(10) |>Seq.toArray
Normal.sampleNormalBAD() |> Seq.take(10) |>Seq.toArray
答案 0 :(得分:4)
在第一个样本randomNormal()
是一个函数,它需要()
并返回一个值,每次都会对它进行评估。
在第二个randomNormal
是一个值,所以它不会被评估两次,一旦有界,它将保持相同的值。
如果翻转randomNormal()
签名是:
unit->seq<float>
和randomNormal
只是:
seq<float>
更新:它保持打印,因为printfn
在序列内,这是有界值。
如果您尝试在最后一行之前在身体中打印,您将看到差异。这是一个简化的示例代码:
let sampleNormal =
fun () ->
let rec randomNormal() =
let u1, u2 = 1,2
printfn "Evaluating"
seq { yield u1; yield u2 ; printfn "next";yield! randomNormal() }
randomNormal()
let sampleNormalBAD =
fun () ->
let rec randomNormal =
let u1, u2 = 1,2
printfn "Evaluating"
seq { yield u1; yield u2 ; printfn "next";yield! randomNormal }
randomNormal
答案 1 :(得分:0)
完成Gustavo的回答,randomNormal
是一个值,在由解释器计算后,绑定到一个序列。
对randomNormal
的进一步调用将产生此序列,并且在序列之前使用的绑定没有理由被评估。 t,theta等...将始终具有相同的值。
什么是 ,但序列将被评估,因此打印。
在randomNormal()
的情况下,同样的情况发生,但是评估绑定,因为函数可能依赖于副作用。