1

我需要一个在 F# 中产生素数的函数。我找到了这个:

let primesSeq = 
    let rec nextPrime n p primes =
        if primes |> Map.containsKey n then
            nextPrime (n + p) p primes
        else
            primes.Add(n, p)

    let rec prime n primes =
        seq {
            if primes |> Map.containsKey n then
                let p = primes.Item n
                yield! prime (n + 1) (nextPrime (n + p) p (primes.Remove n))
            else
                yield n
                yield! prime (n + 1) (primes.Add(n * n, n))
        }

    prime 2 Map.empty

这很好用,但有时我也需要使用 int64/BigInts。有没有比提供像这样的其他序列更聪明的方法来重用这段代码:

let primesSeq64 = Seq.map int64 primesSeq
let primesBigInts = Seq.map (fun (x : int) -> BigInteger(x)) primesSeq

我听说过使用“inline”和“LanguagePrimitives”修改代码,但我发现的只是与函数有关,而我的问题与一个值有关。

此外 - 我想要一个可以处理整数类型并计算平方根下限的函数。

let inline sqRoot arg = double >> Math.Sqrt >> ... ?

但我看不到返回与“arg”相同类型的方法,因为 Math.Sqrt 返回一个双精度值。再说一遍 - 有什么比我自己重新实现计算平方根的逻辑更好的方法吗?

4

2 回答 2

4

因此,执行此操作的一般方法需要一个函数和语言原语 - 在您的情况下,您所1编写的任何地方都会根据需要LanguagePrimitives.GenericOne产生1等等。1.0

要使其工作,您需要创建一个函数值 - 您可以通过执行以下操作来避免这种情况:

let inline primesSeq() = ...
let primesintSeq = primesSeq() //if you use this as an int seq later the compiler will figure it out, otherwise you use
let specified : int seq = primesSeq()

不过,我对 sqrt 的情况不太确定——这可能取决于你愿意做出解决方案的程度。

于 2014-01-01T00:36:39.557 回答
2

一个简单的泛型实现sqRoot可能会遵循以下原则:

let sqRoot arg =
    let inline sqrtd a = (double >> sqrt) a
    let result = match box(arg) with
                    | :? int64 as i -> (sqrtd i) |> int64 |> box
                    | :? int as i -> (sqrtd i) |> int |> box
                    // cases for other relevant integral types
                    | _ -> failwith "Unsupported type"
    unbox result

然后,检查 FSI:

> let result: int = sqRoot 4;;
val result : int = 2
> let result: int64 = sqRoot 9L;;
val result : int64 = 3L
于 2014-01-01T01:56:31.223 回答