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 が言ったように、基本的なエラーは、関数をタプル形式で宣言したが、カリー化された形式で使用したことです。

cdfとパターンマッチしていることに気付きましたp。新しい値pは のパラメータpを隠しますthis.InverseCDF。したがって、そのパラメーターを比較することはできなくなりました。あなたは実際にそれ自体と比較cdfし、2 つのガードは常にであり、これはまったく必要ありません。cdfwhenfalse

いくつかの修正:

  1. 特定のリテラルとの一致ではなく、cdfその値を とのみ比較するため、パターン マッチングから削除します。p
  2. whenガードを2 つ上に移動します。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) = 

これは、関数を呼び出すときにカリー化されたスタイルを使用したf a bが、定義にはタプルされたスタイルがあるためですf (a,b)

また、あなたのマッチケースは完全に正しくありません.2番目のケースがそれらをつかむため、最後の2つのケースは決してマッチしません.おそらく

    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 に答える