Есть ли трюки для выполнения неявных преобразований в 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"