11

私は特定のトピックを尋ねるためにここにいます-私は実際にこれについての情報をウェブ上でほとんど見つけませんでした。MinimaxアルゴリズムのF#バージョンを実装しています。私が今抱えている問題は、ツリーのリーフ(以下のデータ構造)を比較したいということです。VSが私にくれたエラーを検索して、私は次のようなものにたどり着きました。

私が持っていた木のタイプ:

type TreeOfPosition =
    | LeafP   of Position
    | BranchP of Position * TreeOfPosition list

そしてIComparableを実装するための誘惑

type staticValue = int
[<CustomEquality;CustomComparison>]
type TreeOfPosition =
    | LeafP   of Position * staticValue
    | BranchP of Position * TreeOfPosition list

    override x.Equals(yobj) = 
        match yobj with
        | :? TreeOfPosition as y -> (x = y)
        | _ -> false

    override x.GetHashCode() = hash (x)
    interface System.IComparable with
        member x.CompareTo yobj =
            match yobj with
            | :? TreeOfPosition as y -> compare (x) (y)
            | _ -> invalidArg "yobj" "cannot compare value of different types"

最後に、LeafPのリストの最大値(および最小値)を静的な値で取得したいだけです(他の関数で計算します)。

上記のコードはコンパイルされます。ただし、これでテストします。

let p = new Position()
p.Add(1,BLACK)
let a = LeafP(p,1)
let b = LeafP(p,2)

let biger = compare a b
printf "%d" biger

GetHashCodeのオーバーライドの"|:? TreeOfPosition as y-> compare(x)(y)"行にSystem.StackOverflowExceptionが発生しました。

ミニマックスについて話し合っているので、hubfs.net(http://cs.hubfs.net/forums/thread/15891.aspx )にスレッドがあります。ここに私の最新のコードがあります(http://www.inf.ufrgs.br/~pmdusso/works/Functional_Implementation_Minimax_FSharp.htm

前もって感謝します、

ペドロ・デュッソ

ええと、私はその考えを非常にはっきりと理解しましたが、それを機能させることはできません。リーフのリスト(「List.max」:P)から最大の静的値を持つリーフを取得したいことを思い出して、CompareToまたはEqualsを実装すると、List.maxがそれらで機能するようになると思います。私はこのようなものを構成します:

let mycompare x y = 
  match x, y with
  // Compare values stored as part of your type
  | LeafP(_, n1), LeafP(_, n2) -> compare n1 n2
  //| BranchP(_, l1), BranchP(_, l2) -> compare l1 l2 //I do not need Branch lists comparison
  | _ -> 0 // or 1 depending on which is list...

[< CustomEquality;CustomComparison >]
type TreeOfPosition =
    | LeafP   of Position * int
    | BranchP of Position * TreeOfPosition list

    override x.Equals(yobj) = 
       match yobj with
       | :? TreeOfPosition as y -> (x = y)
       | _ -> false

    override x.GetHashCode() = hash (x)
    interface System.IComparable with
       member x.CompareTo yobj = 
          match yobj with 
          | :? TreeOfPosition as y -> mycompare x y
          | _ -> invalidArg "yobj" "cannot compare value of different types" 

私がこのように関数を配置している問題は次のとおりです。

1)パターン弁別器「LeafP」が定義されていません(LeafPに赤い下線が引かれています)

2)(77,39):エラーFS0039:値またはコンストラクター'mycompare'が定義されていません。ALTENTERを実行しようとすると、このメッセージがF#インタラクティブに表示されます。位置{77,39}は、(GetHashCode内の)mycompare呼び出しの開始に対応します。

私が間違っているのは何ですか?何を改善できますか?

どうもありがとう、

ペドロ・デュッソ

編集3-解決済み

はい!私はあなたの答えを最終的に機能させるために管理します!

最終的なコードは次のとおりです。

[<CustomEquality;CustomComparison>]
type TreeOfPosition =
    | LeafP   of Position * int
    | BranchP of Position * TreeOfPosition list

    //Func: compare
    //Retu: -1: first parameter is less than the second
    //       0: first parameter is equal to the second
    //       1: first parameter is greater than the second
    static member mycompare (x, y) = 
        match x, y with
        // Compare values stored as part of your type
        | LeafP(_, n1), LeafP(_, n2) -> compare n1 n2
        | _ -> 0 // or 1 depending on which is list...

    override x.Equals(yobj) = 
        match yobj with
        | :? TreeOfPosition as y -> (x = y)
        | _ -> false

    override x.GetHashCode() = hash (x)
    interface System.IComparable with
       member x.CompareTo yobj = 
          match yobj with 
          | :? TreeOfPosition as y -> TreeOfPosition.mycompare(x, y)
          | _ -> invalidArg "yobj" "cannot compare value of different types" 

フィードバックをお寄せいただきありがとうございます!

ペドロ・デュッソ

4

1 に答える 1

9

まず、関数が比較している値のメソッド(つまり)をcompare呼び出すため、例外が発生します。のカスタム実装で使用して比較している値は、(ランタイムによって)比較するように求められている値であるため、これによりスタックオーバーフローが発生します。CompareTox.ComaperTo(y)compareCompareTo

CompareToまたはを実装する通常の方法Equalsは、タイプに格納する一部の値のみを比較することです。たとえば、次のように書くことができます。

編集mycopare:比較を行うためのヘルパー関数を書くことができます(または単にCompareTo実装を変更することもできます)。ただし、関数を使用する場合は、関数を型宣言内に移動する必要があります(型を認識できるようにするため、F#では宣言の順序が重要であることに注意してください)。

それを書く1つの方法はこれです:

[<CustomEquality; CustomComparison >] 
type TreeOfPosition = 
  | LeafP   of Position * int 
  | BranchP of Position * TreeOfPosition list 

  override x.Equals(yobj) =  
     match yobj with 
     | :? TreeOfPosition as y -> 
        // TODO: Check whether both y and x are leafs/branches
        // and compare their content (not them directly)
     | _ -> false 
  override x.GetHashCode() = // TODO: hash values stored in leaf/branch

  interface System.IComparable with 
     member x.CompareTo yobj =  

       // Declare helper function inside the 'CompareTo' member
       let mycompare x y = 
         match x, y with
         // Compare values stored as part of your type
         | LeafP(_, n1), LeafP(_, n2) -> compare n1 n2
         | BranchP(_, l1), BranchP(_, l2) -> compare l1 l2
         | _ -> -1 // or 1 depending on which is list...

       // Actual implementation of the member
       match yobj with 
       | :? TreeOfPosition as y -> mycompare x y
       | _ -> invalidArg "yobj" "cannot compare value of different types" 

を呼び出すたびcompareにデータの一部しか取得されないため、これは機能します。そのため、ある程度の進歩が見られます。

于 2010-06-22T13:27:54.570 に答える