我想知道为什么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)
答案 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)