是否有在F#中进行隐式转换的技巧?

时间:2010-11-02 05:38:07

标签: f#

考虑这个F#代码,将i下面的数字加上3和5的倍数:

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

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

由于iint,如果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 s。这是因为F#不进行隐式转换。

是否有一种简单的方法可以解决这个问题,或者在6个地方添加I是最好的选择?

2 个答案:

答案 0 :(得分:6)

这并不完全回答您的问题,但请注意,通过定义您自己的数字文字也可以使sequenceOfMultiples成为通用的:

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"

答案 1 :(得分:5)

你做得最好。

(没有比通过添加你添加的六个字符更容易“绕过”它。即使没有隐式转换,F#也比C#短,并且delta更改从int到BigInteger F#中的数字也比C#小。所以不要为隐含转换的丢失感到难过 - 对所有其他简洁的胜利感到高兴。:))