【问题标题】:Generalizing functions in F#F# 中的泛化函数
【发布时间】:2014-01-01 00:27:13
【问题描述】:

我需要一个在 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 返回一个双精度值。再说一遍 - 还有什么比我自己重新实现计算平方根的逻辑更好的方法吗?

【问题讨论】:

    标签: optimization f# inline automatic-generalization


    【解决方案1】:

    因此,执行此操作的一般方法需要一个函数和语言原语 - 在您的情况下,无论您在哪里拥有 1,您都会编写 LanguagePrimitives.GenericOne,这将根据需要产生 11.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 的情况 - 这可能取决于您愿意解决的问题。

    【讨论】:

      【解决方案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
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-05-28
        • 2021-04-01
        • 2016-09-30
        相关资源
        最近更新 更多