Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Are there tricks for doing implicit conversions in F#?

Tags:

f#

Consider this F# code to sum the numbers below i that are multiples of 3 and 5:

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

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

Since i is an int, you'll overflow if i is large. This version with BigInteger takes care of that:

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

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

To convert the int version to the BigInteger version, I had to add lots of Is after the numbers. This is because F# doesn't do implicit conversions.

Is there an easy way to get around this, or was adding Is in 6 places the best thing to do?

like image 594
user392226 Avatar asked Nov 02 '10 05:11

user392226


1 Answers

This doesn't exactly answer your question, but note that it's also possible to make sequenceOfMultiples generic by defining your own numeric literal:

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"
like image 68
kvb Avatar answered Nov 15 '22 11:11

kvb