3

我想知道为什么 F-Sharp 不支持无穷大。

这适用于 Ruby(但不适用于 f#):

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

-> System.DivideByZeroException:试图除以零。

我可以以非常复杂的方式编写相同的功能:

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

-> 作品

但是我认为第一个会更清楚。我找不到在 F# 中使用动态类型无穷大的简单方法。有 infinity 关键字,但它是浮动的:

let a = Math.bigint +infinity;;

System.OverflowException:BigInteger 不能表示无穷大。在 System.Numerics.BigInteger..ctor(Double value) at .$FSI_0045.main@() 由于错误而停止


编辑:这似乎也适用于迭代:

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

2 回答 2

8

首先,F# 列表不是惰性的(我不确定 Ruby 列表是惰性的),所以即使有一个一般的无穷大概念,您的第一个示例也永远无法工作。

其次,Int32 中没有无穷大值。只有最大值。不过 Double 有正无穷和负无穷。

放在一起,这有效:

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

但是我觉得 Seq.initInfinite 是你最好的选择。上面的代码对我来说看起来很奇怪。(或者至少使用 Double.PositiveInfinity 而不是 1./0。)

乍一看,语言中的一个不错的选择是像 haskell 中的无限范围运算符: seq { 1.. } 问题是它只适用于 seq,所以我想支持后缀运算符的额外工作是仅此功能不值得。

底线:在我看来,使用 Seq.initInfinite。

于 2009-10-13T09:30:13.457 回答
3

我认为以下是 F# 中无限范围的最佳解决方案;通过标记inline我们比“动态类型无穷大”做得更好的函数,我们得到结构类型无穷大范围(适用于 int32、int64、bigint,...任何具有静态成员的类型,该成员+接受两个自己类型的参数并返回一个它自己的类型的值):

let inline infiniteRange start skip = 
    seq {
        let n = ref start
        while true do
            yield n.contents
            n.contents <- n.contents + skip
    }

//val inline infiniteRange :
//   ^a ->  ^b -> seq< ^a>
//    when ( ^a or  ^b) : (static member ( + ) :  ^a *  ^b ->  ^a)
于 2010-11-21T22:28:09.647 回答