F-Sharp (F #) нетипизированная бесконечность - PullRequest
3 голосов
/ 13 октября 2009

Интересно, почему 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 ]

8 голосов
/ 13 октября 2009

Прежде всего, списки 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.

3 голосов
/ 22 ноября 2010

Я думаю, что следующее является лучшим решением для бесконечных диапазонов в 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)
...