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 キーワードがありますが、float です:

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 には無限値がありません。MaxValue のみ。ただし、Double には正と負の無限大があります。

まとめると、これは機能します:

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

ただし、 Seq.initInfinite が最良の選択肢だと思います。上記のコードは私には奇妙に見えます。(または、少なくとも 1./0 の代わりに Double.PositiveInfinity を使用してください。)

一見すると、この言語にあると便利なオプションは、haskell のような無限範囲演算子です: seq { 1.. } 問題は、それが seq に対してのみ機能することです。したがって、後置演算子をサポートするための余分な作業はこの機能だけでは価値がありません。

結論: 私の意見では、Seq.initInfinite を使用します。

于 2009-10-13T09:30:13.457 に答える
3

以下は、F# の無限範囲に対する最良の解決策だと思います。inline「動的に型付けされた無限」よりも優れている関数をマークすることにより、構造的に型付けされた無限の範囲を取得します(int32、int64、bigint、...+独自の型の2つの引数を取り、返す静的メンバーを持つ任意の型で動作します独自の型の値):

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 に答える