2012-09-26 21 views
1

通過嘗試重新創建使用遞歸的簡單二分法,繼續今天的F#學習,此處我使用MathNet庫從Beta分佈中繼承。F#值不是函數錯誤

我收到函數「搜索」(二進制搜索方法)錯誤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的當前值,因此我的前兩個匹配模式看起來很可疑。

回答

6

正如@John所說的,你的根本錯誤是你在tuple表單中聲明瞭這個函數,但是以curry的形式使用了它。

我注意到你模式匹配cdfp。新值p將影響參數pthis.InverseCDF;因此,該參數不再用於比較。你實際上將cdfcdf本身進行比較,並且兩個when後衛始終是false,這是你根本不需要的。

一些更正:

  1. 從模式匹配刪除cdf因爲你只需要它的價值與p比較,不匹配特定的文字。
  2. 移動兩個when後衛。最後的模式不應該是一個when後衛;編譯器會抱怨在這種情況下不完整的模式匹配。
  3. 使用後綴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 
+0

再次感謝+ 1d這是一個非常好的解釋。 –

+0

您可以將兩個中間匹配案例移到頂部,然後將頂部和底部案例合併到一個'_'個案例中。 – ildjarn

+0

@ildjarn,謝謝你的提示。這段代碼看起來很好,並且合併了真實和錯誤的語句,它看起來比C#代碼更好。 –

4

你的定義是在元組的風格,沒有令行禁止的風格 - 只是將其更改爲

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

這是因爲當你調用函數你已經使用了咖喱風格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 
+0

參見http://lorgonblog.wordpress.com/2008/04/03/f-function-types-fun-with-tuples-and-currying/ – Brian

+2

小錯誤 - 這些不是主動模式,而是警衛。 – Tarmil

+0

謝謝。 +1並回答! –