F# 序号:展开F中的解释#

F# 序号:展开F中的解释#,f#,seq.unfold,F#,Seq.unfold,我正试图通过使用F#懒洋洋地创建一个序列 序列定义如下: 序列的第n项 三角形数由,tn给出= ½n(n+1);所以前十个三角形 数字如下: 1,3,6,10,15,21,28,36,45,55, 以下是我到目前为止所做的,但似乎不起作用: let tri_seq = 1.0 |> Seq.unfold (fun x -> match x with

我正试图通过使用F#懒洋洋地创建一个序列

序列定义如下:

序列的第n项 三角形数由,tn给出= ½n(n+1);所以前十个三角形 数字如下:

1,3,6,10,15,21,28,36,45,55,

以下是我到目前为止所做的,但似乎不起作用:

let tri_seq = 1.0 |> Seq.unfold (fun x -> match x with                                         
                                          | _ -> Some (x, 0.5*x*(x + 1.0)))
非常感谢您能帮助我了解unfold的工作原理。谢谢

编辑:我将第一个答案标记为正确,但它不起作用,但是我稍微修改了一下,它就起作用了

let tri_seq = 1.0 |> Seq.unfold (fun x -> Some (0.5 * x * (x + 1.0),x + 1.0))

首先,如果只有一个案例,为什么要使用
match

let tri_seq = 1.0 |> Seq.unfold (fun x -> Some (x, 0.5 * x * (x + 1.0)))
第二,什么“似乎不起作用”?您是否知道您生成了一个无限列表

/编辑:为了完整起见,这里有一个正确的解决方案,OP自己找到了,并将其作为评论发布:

let tri_seq = 
    1.0 |> Seq.unfold (fun x -> Some (0.5 * x * (x + 1.0), x + 1.0))

这里有一个替代方案:

let tri = seq {
    let n = ref 1.0
    let diff = ref 2.0
    while true do
        yield !n
        n := !n + !diff
        diff := !diff + 1.0
    }

printfn "%A" (tri |> Seq.take 10 |> Seq.to_list)

Brian发布的代码的另一种替代方法是使用递归,而不是命令式“while”循环:

let tri = 
  let rec loop(n, diff) = seq { 
    yield n        
    yield! loop(n + diff, diff + 1.0) }
  loop(1.0, 2.0)
printfn "%A" (tri |> Seq.take 10 |> Seq.to_list)

它的效率要低得多(因此您在这里必须小心一点……),但它是更惯用的函数式解决方案,因此可能更容易看到代码的作用。

我知道这是一个非常古老的解决方案,但我不明白为什么在确定x*(x+1)是偶数并且确实可以被2整除的情况下使用float。 所以我只想用这个来代替(我知道差别不大,但至少你有一个int-seq):


(当然,除非你处理的是大量的数据…)

我试过了,但序列只返回一个…>三;;valit:seq=seq[1.0;1.0;1.0;1.0;…]让tri_-seq=1.0 |>seq.unfold(乐趣x->Some(0.5*x*(x+1.0),x+1.0))是我所需要的。非常感谢。谢谢,但是我不知道“Seq{}”是什么意思,不是“yield”关键字,更别说“!”了。如果您能花点时间解释,我们将不胜感激!不是专家,但Seq{}的意思是让我从中得到一个序列。yield与C#相同,表示返回值并等待调用代码请求下一个值。产量is(我相信)与Seq.concat类似-将递归调用返回的Seq变平,并对每个元素进行一次让步。可以做一些努力,至少使
循环
具有尾部递归,否则这将无法扩展anywhere@pqnetF#编译器实际上可以很好地处理递归
seq
表达式,所以这个模式工作得很好(不像C#中的
foreach(x in y)产生x
,这会有问题)@TomasPetricek你是对的,函数实际上是一个尾部调用,因为序列是惰性的,
loop
返回一个序列,然后作为当前序列的延续返回。如果
屈服
屈服的顺序正好相反,这可能会有问题,但这样就可以进行优化
let tri_seq = 1 |> Seq.unfold (fun x -> Some (x * (x + 1) / 2 , x + 1)) 

tri_seq |> Seq.take 6 |> Seq.toList //[1; 3; 6; 10; 15; 21]