我想创建一个数字序列,其中每个数字是前面所有数字加上一个随机数的总和。
我试着这样做:
let random = new System.Random()
let addRandom =
seq{let rec stepRandom acc =
let step = random.Next(0,10)
yield! acc+step //-----wont accept this
stepRandom (acc+step)
stepRandom 0 }
问题是它不会接受递归函数内的yield。
我可以看到一个具有可变值积累的解决方案,但是如何以惯用的方式解决这个问题呢?
答案 0 :(得分:5)
使用可爱的unfold
函数:
let random = new System.Random()
let r() = random.Next(0, 10)
let s = Seq.unfold (fun acc -> Some(acc, acc+r())) (r())
Unfold从初始状态(在本例中为第一个随机数 - 第二个参数)和生成器函数(第一个参数)创建一个序列,该序列采用先前的状态并产生(1)一个新状态(在这种情况下是前一个状态加上随机的总和)和(2)序列中的一个新元素(前一个状态)。
答案 1 :(得分:4)
如果将序列表达式与内部函数对齐,那么它将成为一个自然的递归函数定义。另外,按照你的描述,你想要产生累加器(或新的和),而不是新的随机int。
let random = new System.Random()
let addRandom =
let rec stepRandom acc = seq{
let step = random.Next(0,10)
yield acc
yield! stepRandom (acc + step) }
stepRandom 0
答案 2 :(得分:3)
另一种选择是将Seq.initInfinite与Seq.scan:
一起使用let rand = System.Random()
let s = Seq.initInfinite (fun _ -> rand.Next(0, 10))
|> Seq.scan (+) 0
|> Seq.skip 1
答案 3 :(得分:3)
seq { let rand = System.Random()
while true do
yield rand.Next(0, 10) }
|> Seq.scan (+) 0