F-Sharp(F#)无类型无限

时间:2009-10-13 08:03:31

标签: f# functional-programming infinite-loop infinity lazylist

我想知道为什么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#中使用动态类型无穷大的任何简单方法。 有无限关键字,但它是浮点数:

let a = Math.bigint +infinity;;

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


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

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

2 个答案:

答案 0 :(得分:8)

首先,F#列表并不是懒惰的,(我不确定Ruby列表是否很懒),所以即使使用无穷大概念,你的第一个例子也无法工作。

其次,Int32中没有无穷大值。只有MaxValue。 Double中有正负无穷大。

把它放在一起,这有效:

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

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

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

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

答案 1 :(得分: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)