1

今天继续我的 F# 学习,尝试使用递归重新创建一个简单的二分法,这里我使用 MathNet 库从 Beta 发行版继承。

我收到有关“搜索”功能(二进制搜索方法)的错误消息the value is not a function and cannot be applied

//Beta class inheriting from MathNet Beta distribution
//Extends the class by implementing an InverseCDF function

type newBeta(alpha:double, beta:double) =
    inherit MathNet.Numerics.Distributions.Beta(alpha, beta)

member this.InverseCDF(p: float) =
    let rec search (min: float, max: float, acc: uint32) = 
        let x = (min + max) / 2.0
        let error = 0.001
        let maxiters : uint32 = 1000u
        let cdf = this.CumulativeDistribution(x)

        match cdf, (Math.Abs(cdf - p) < error || acc > maxiters) with   //while statement
        | _ , true                  -> cdf      //auto match cdf and if while statement evaluates true then break and return cdf result
        | p , _                     -> cdf      //if exactly matches p then break and return cdf result
        | p , false when p > cdf    -> search (min) (x) (acc + 1)   //if p > cdf then set max = x and increment then call func with new params
        | p , false when p < cdf    -> search (x) (max) (acc + 1)   //if p < cdf then set min = x and increment then call func with new params

    search (0.0) (1.0) (0)  //Call the bisection method with initial parameters

任何人都可以帮忙吗?同样显然,任何关于如何使其更具“功能性”的输入都会很酷。由于错误,尚未能够运行此测试。我的前 2 个匹配模式看起来很可疑,因为我试图返回cdf.

4

2 回答 2

6

正如@John 所说,您的基本错误是您以元组形式声明了该函数,但以咖喱形式使用了它。

我注意到您cdfp. 新值将隐藏p参数pthis.InverseCDF因此,该参数不再可用于比较。你居然cdfcdf自己比,两个when守卫总是false,你根本不想要。

一些更正:

  1. 从模式匹配中删除cdf,因为您只想将其值与 比较p,而不是与特定文字匹配。
  2. 将两名when守卫向上移动。最后一个模式不应该是when守卫;在这种情况下,编译器会抱怨不完整的模式匹配。
  3. 对(类型为 )u的任何算术运算使用后缀。accunint32

search功能:

let rec search (min: float) (max: float) (acc: uint32) = 
    let x = (min + max) / 2.0
    let error = 0.001
    let maxiters : uint32 = 1000u
    let cdf = this.CumulativeDistribution(x)

    match abs(cdf - p) < error || acc > maxiters with   // while statement
    | false when p > cdf    -> search min x (acc + 1u)   // if p > cdf then set max = x and increment then call func with new params
    | false when p < cdf    -> search x max (acc + 1u)   // if p < cdf then set min = x and increment then call func with new params 
    | _                     -> cdf      // if exactly matches p or returns true then break and return cdf result

search 0.0 1.0 0u  // call the bisection method with initial parameters
于 2012-09-26T06:00:23.917 回答
4

您的定义是元组风格,而不是咖喱风格 - 只需将其更改为

let rec search (min: float) (max: float) (acc: uint32) = 

这是因为当您调用该函数时,您使用了 curried 样式f a b,但您的定义具有元组样式f (a,b)

此外,您的匹配案例并不完全正确 - 最后两种情况永远不会匹配,因为第二种情况会抓住它们 - 您可能想要

    match cdf, (Math.Abs(cdf - p) < error || acc > maxiters) with   //while statement
    | _ , true                  -> cdf      //auto match cdf and if while statement evaluates true then break and return cdf result
    | p when p=cdf, _                     -> cdf      //if exactly matches p then break and return cdf result
    | p , false when p > cdf    -> search (min) (x) (acc + 1)   //if p > cdf then set max = x and increment then call func with new params
    | p , false when p < cdf    -> search (x) (max) (acc + 1)   //if p < cdf then set min = x and increment then call func with new params
于 2012-09-26T00:26:19.740 回答