确定, 所以我需要一个所有正整数的列表。 首先想到的是:
let numbers:Seq<bigint>=Seq.initInfinite n...
但initInfite实际上并不是infitint:http://msdn.microsoft.com/en-us/library/ee370429.aspx (与bigint不同)它唯一:Int32.MaxValue = 2,147,483,647,这远远不够大。
目前我的计划是用某种手工制作的类替换序列(可能会暗示IEnumerable)。它会很简单(可能对我的使用更有效)但我想知道如何做到这一点
答案 0 :(得分:12)
Seq.unfold (fun n -> Some(n, n + 1I)) 0I
答案 1 :(得分:5)
let numbers:bigint seq =
let rec loop n = seq { yield n; yield! loop (n+1I) }
loop 0I
答案 2 :(得分:3)
我保持以下静态约束函数,因为它非常灵活(您可以指定起始值和跳过间隔)并适用于所有数字类型:
let inline infiniteRange start skip =
seq {
let n = ref start
while true do
yield n.contents
n.contents <- n.contents + skip
}
FSI提供的类型签名:
val inline infiniteRange :
^a -> ^b -> seq< ^a>
when ( ^a or ^b) : (static member ( + ) : ^a * ^b -> ^a)
以下是生成所有正整数的方法(BigInts,即 - 在FSI中显示):
> infiniteRange 1I 1I;;
val it : seq<System.Numerics.BigInteger> =
seq [1 {IsEven = false;
IsOne = true;
IsPowerOfTwo = true;
IsZero = false;
Sign = 1;}; 2 {IsEven = true;
IsOne = false;
IsPowerOfTwo = true;
IsZero = false;
Sign = 1;}; 3 {IsEven = false;
IsOne = false;
IsPowerOfTwo = false;
IsZero = false;
Sign = 1;}; 4 {IsEven = true;
IsOne = false;
IsPowerOfTwo = true;
IsZero = false;
Sign = 1;}; ...]
更新,正如Daniel所示,您可以使用通用语言基元轻松地编写另一个静态约束函数infiniteRange
,内置跳过1:
let inline infiniteRangeSkip1 start =
infiniteRange start LanguagePrimitives.GenericOne
这是类型签名:
val inline infiniteRangeSkip1 :
^a -> seq< ^a>
when ( ^a or ^b) : (static member ( + ) : ^a * ^b -> ^a) and
^b : (static member get_One : -> ^b)
答案 3 :(得分:2)
如果这是您经常需要的话,您甚至可以考虑扩展Seq
模块。
module Seq =
let initInfiniteBig =
seq {
let i = ref 0I
while true do
yield !i
i := !i + 1I
}
let ten = Seq.initInfiniteBig |> Seq.take 10
我对一些变化进行了基准测试:
let initInfiniteBig =
seq {
let i = ref 0I
while true do
yield !i
i := !i + 1I
}
let initInfiniteBig2 =
seq {
let i = ref 0I
while true do
yield i.contents
i.contents <- i.contents + 1I
}
let initInfiniteBig3 =
let rec loop i =
seq {
yield i
yield! loop (i + 1I)
}
loop 0I
let initInfiniteBig4 = Seq.unfold (fun n -> Some(n, n + 1I)) 0I
let range s = s |> Seq.take 100000000 |> Seq.length |> ignore
range initInfiniteBig //Real: 00:00:29.913, CPU: 00:00:29.905, GC gen0: 0, gen1: 0, gen2: 0
range initInfiniteBig2 //Real: 00:00:30.045, CPU: 00:00:30.045, GC gen0: 0, gen1: 0, gen2: 0
range initInfiniteBig3 //Real: 00:00:40.345, CPU: 00:00:40.310, GC gen0: 2289, gen1: 5, gen2: 0
range initInfiniteBig4 //Real: 00:00:30.731, CPU: 00:00:30.716, GC gen0: 1146, gen1: 4, gen2: 1
这是一个通用范围函数,如Stephen's,但没有start
和skip
。
let inline infiniteRange() : seq<'a> =
let zero : 'a = LanguagePrimitives.GenericZero
let one : 'a = LanguagePrimitives.GenericOne
seq {
let n = ref zero
while true do
yield !n
n := !n + one
}
这是签名:
unit -> seq< ^a>
when ^a : (static member get_Zero : -> ^a) and
^a : (static member get_One : -> ^a) and
^a : (static member ( + ) : ^a * ^a -> ^a)
基准:
range (infiniteRange() : seq<bigint>) //Real: 00:00:30.042, CPU: 00:00:29.952, GC gen0: 0, gen1: 0, gen2: 0