Есть ли трюки для выполнения неявных преобразований в F #?

Рассмотрим этот код F #, чтобы суммировать числа ниже i, которые кратно 3 и 5:

let isMultipleOfThreeOrFive n = 
    (n % 3 = 0) || (n % 5 = 0)

let sequenceOfMultiples i =
    seq {1 .. i - 1} |> Seq.filter isMultipleOfThreeOrFive

Так как i является int, вы переполняете, если i велико. Эта версия с BigInteger позаботится об этом:

let isMultipleOfThreeOrFive n = 
    (n % 3I = 0I) || (n % 5I = 0I)

let sequenceOfMultiples (i : System.Numerics.BigInteger) =
    seq {1I .. i - 1I} |> Seq.filter isMultipleOfThreeOrFive

Чтобы преобразовать версию int в версию BigInteger, мне пришлось добавить много i после чисел. Это связано с тем, что F # не выполняет неявных преобразований.

Есть ли простой способ обойти это или добавить i в 6 местах, что лучше всего делать?

Ответы

Ответ 1

Ты сделал лучшее.

(Нет более простого способа "обойти" его, чем путем добавления шести символов, которые вы добавили. Даже без неявных преобразований F # короче, чем С#, а дельта-изменение от-int-to-BigInteger также меньше в F #, чем С#. Так что не печальтесь о потере имплицитного преобразования - будьте счастливы, когда выиграет еще одна победа.:))

Ответ 2

Это точно не отвечает на ваш вопрос, но обратите внимание, что также можно сделать sequenceOfMultiples generic, указав свой собственный числовой литерал:

module NumericLiteralG =
  let inline FromZero() = LanguagePrimitives.GenericZero
  let inline FromOne() = LanguagePrimitives.GenericOne
  let inline FromInt32 (i:int) =
    let zero : ^a = FromZero()
    let one : ^a = FromOne()
    let rec compute : int -> ^a = function
    | 0 -> zero
    | n -> 
        let half = compute (n/2)
        let whole = half + half
        if (n%2 = 0) then whole
        else whole + one
    compute i

let inline isMultipleOfThreeOrFive n = 
    (n % 3G = 0G) || (n % 5G = 0G)

let inline sequenceOfMultiples i =
    seq {1G .. i - 1G} |> Seq.filter isMultipleOfThreeOrFive

let bigintSeq = sequenceOfMultiples 100I
let intSeq = sequenceOfMultiples 100

// doesn't compile
let stringSeq = sequenceOfMultiples "100"