F-夏普(F#)非类型无穷大

F-夏普(F#)非类型无穷大,f#,functional-programming,infinite-loop,infinity,lazylist,F#,Functional Programming,Infinite Loop,Infinity,Lazylist,我想知道为什么F-Sharp不支持无穷大 这在Ruby(但在f#)中不起作用: ->System.DivideByZeroException:尝试除以零 我可以用非常复杂的方式编写相同的功能: let numbers n = 1 |> Seq.unfold (fun i -> Some (i, i + 1)) |> Seq.take(n) ->工作 然而,我认为第一个问题会更加清楚。 我找不到任何简单的方法在F#中使用动态类型的无穷大。 有infinity关键字,但它是flo

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

这在Ruby(但在f#)中不起作用:

->System.DivideByZeroException:尝试除以零

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

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

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

let a = Math.bigint +infinity;;
System.OverflowException:BigInteger不能表示无穷大。 在System.Numerics.BigInteger..ctor处(双值) 地址:$FSI_0045.main@) 由于错误而停止


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

首先,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。

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

让内联不定式开始跳过=
序号{
设n=ref开始
尽管如此
产量
n、 目录^b->seq<^a>
//当(^a或^b):(静态成员(+):^a*^b->^a)

它是在做整数运算还是浮点运算?这两者对无穷大的概念截然不同。这在Ruby中不起作用。无穷大在Ruby中也是一个浮点值,所以你需要做浮点除法-1..1.0/0。在这种特殊情况下,“让数字n=seq{1..n}”可能是最简单的…Johan,seq.take(n)在我的实际代码中没有,这只是为了演示目的。:-)是的,我猜是这样的…:)我发现无穷大问题在编程环境中非常有趣-并且相信你经常会有一个自然的限制…-但这是另一个问题…因为Seq.initInfinite基于Int32,所以出于任何实际目的,等同于'seq{1..System.Int32.MaxValue}“.相反,使用这个构造,没有人会被愚弄到相信任何有限性实际上都涉及其中。我建议这样做。-或者使用展开方法-在处理bigint时…@Johan:我觉得Seq.initInfinite使用类型推断更有效-结果Seq的类型应该自动推断,而使用{1..Int32.MaxValue}您需要调用某个常量。因此,这可能是与原始问题更接近的解决方案。但实际上,initInfinite中的无限是一个用词不当的问题。
let numbers n = Seq.initInfinite (fun i -> i+1) |> Seq.take(n)
let numbers n = seq { 1. .. 1./0. } |> Seq.take(n)
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)