今天通过尝试使用递归重新创建一个简单的二分法来继续我的F#学习,这里我使用MathNet库继承Beta版本。
我在函数'search'(二进制搜索方法)上收到错误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
有人可以帮忙吗?显然,任何关于如何使这更“功能”的输入都会很酷。但由于错误,尚未能运行此测试。鉴于我正在尝试返回cdf
的当前值,我的前2个匹配模式看起来很可疑。
答案 0 :(得分:6)
正如@John所说,你的根本错误是你以元组形式声明了这个函数,但是以curry形式使用它。
我注意到您将cdf
与p
进行了模式匹配。新值p
将影响p
的参数this.InverseCDF
;因此,该参数不再可用于比较。您实际上将cdf
与cdf
本身进行了比较,并且两个when
警卫总是false
,您根本不需要这些。
一些更正:
cdf
,因为您只想将其值与p
进行比较,与特定文字不匹配。when
警卫。最后一个模式不应该是when
后卫;在这种情况下,编译器会抱怨模式匹配不完整。u
(类型为acc
)的任何算术运算使用后缀unint32
。新的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
答案 1 :(得分:4)
您的定义是元组样式,而不是咖喱风格 - 只需将其更改为
即可let rec search (min: float) (max: float) (acc: uint32) =
这是因为当您调用该函数时,您使用了curried样式f a b
,但您的定义具有tupled样式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