Initializing an endless list of BigIntegers

Ok, so I need a list of all positive integers. The first thing that comes to mind is:

let numbers:Seq<bigint>=Seq.initInfinite n...

but initInfite is not actually infitint: http://msdn.microsoft.com/en-us/library/ee370429.aspx (unlike bigint) its only one: Int32.MaxValue = 2,147,483,647, which is nowhere big enough.

My current plan is to replace the sequence with some kind of handmade class (possibly using IEnumerable). That would be simple (and perhaps more efficient for my use), but I want to know how to do it

+5
source share
4
let numbers:bigint seq = 
    let rec loop n = seq { yield n; yield! loop (n+1I) }
    loop 0I
+5
Seq.unfold (fun n -> Some(n, n + 1I)) 0I
+11

, ( ) :

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;}; ...]

: , , , infiniteRange skip 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

, 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

Update

:

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

2

There is a common range function here, for example Stephen's, but without startand 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
  }

Here's the signature:

unit -> seq< ^a>
    when  ^a : (static member get_Zero : ->  ^a) and
          ^a : (static member get_One : ->  ^a) and
          ^a : (static member ( + ) :  ^a *  ^a ->  ^a)

And the standard:

range (infiniteRange() : seq<bigint>) //Real: 00:00:30.042, CPU: 00:00:29.952, GC gen0: 0, gen1: 0, gen2: 0
+2
source

All Articles