F-升号 (F#) 无类型无穷大

发布于 2024-08-08 10:52:47 字数 736 浏览 8 评论 0原文

我想知道为什么 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 关键字,但它是 float:

let a = Math.bigint +infinity;;

System.OverflowException:BigInteger 无法表示无穷大。 在 System.Numerics.BigInteger..ctor(双值) 在.$FSI_0045.main@() 由于错误而停止


编辑:这似乎也可以在迭代中工作:

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

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)

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

幽蝶幻影 2024-08-15 10:52:47

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

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.

时常饿 2024-08-15 10:52:47

我认为以下是 F# 中无限范围的最佳解决方案;通过标记函数内联,我们比“动态类型无限”做得更好,我们得到结构类型无限范围(适用于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)

I think the following is the best solution to infinite ranges in F#; by marking the function inline we do better than "dynamically typed infinity" we get structurally typed infinite ranges (works with int32, int64, bigint, ... any type that which has a static member + which takes two arguments of its own type and returns a value of it's own type):

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)
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文