views:

421

answers:

1

I wonder why F-Sharp doesn't support infinity.

This would work in Ruby (but not in f#):

let numbers n = [1 .. 1/0] |> Seq.take(n)

-> System.DivideByZeroException: Attempted to divide by zero.

I can write the same functionality in much complex way:

let numbers n = 1 |> Seq.unfold (fun i -> Some (i, i + 1)) |> Seq.take(n)

-> works

However I think that first one would be much more clear. I can't find any easy way to use dynamically typed infinity in F#. There is infinity keyword but it is float:

let a = Math.bigint +infinity;;

System.OverflowException: BigInteger cannot represent infinity. at System.Numerics.BigInteger..ctor(Double value) at .$FSI_0045.main@() stopped due to error


Edit: also this seems to work in iteration:

let numbers n = Seq.initInfinite (fun i -> i+1) |> Seq.take(n)
+7  A: 

First of all, F# lists are not lazy, (I'm not sure Ruby lists are lazy), so even with a general notion of infinity your first example can never work.

Second, there is no infinity value in Int32. Only MaxValue. There is a positive and negative infinity in Double though.

Putting it together, this works:

let numbers n = seq { 1. .. 1./0. } |> Seq.take(n)

I feel however Seq.initInfinite is your best option. The code above looks strange to me. (Or at least use Double.PositiveInfinity instead of 1./0.)

At first sight, a nice option to have in the language would be an infinite range operator like in haskell: seq { 1.. } The problem is that it would only work for seq, so I guess the extra work to support postfix operators is not worth it for this feature alone.

Bottom line: in my opinion, use Seq.initInfinite.

Kurt Schelfthout
Since Seq.initInfinite is based in Int32 it must, for any practical purpose, be equivalent to 'seq { 1 .. System.Int32.MaxValue }'. Using that construct instead nobody is fooled to believe that any inifinity is actually involved. I would recommend that instead. - Or the unfold approach - when dealing with bigints...
Johan Kullbom
@Johan: I feel that Seq.initInfinite works better with type inference - the type of the resulting seq should be inferred automatically, whereas with { 1..Int32.MaxValue} you need a call to some constant. So it may be a closer solution to the original question. But indeed, the infinite in initInfinite is a misnomer.
Kurt Schelfthout