2010-06-22 21 views
8

我在這裏要問一個特定主題 - 我真的在網絡上發現了一些關於此的信息。 我正在實現Minimax算法的F#版本。我現在遇到的問題是我想比較我的樹的葉子(下面的數據結構)。搜索VS送給我的誤差修改我抵達這樣的事情:在F#元組中實現與CustomComparison和CustomEquality的自定義比較

我所用的樹類型有:

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" 

在該temptative結束,我只想通過其靜態值(在其他函數中計算)獲取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 

我在得到了System.StackOverflowException 「|:TreeOfPosition爲y - >比較(X)(Y)」 行中的GetHashCode覆蓋。

我在hubfs.net(http://cs.hubfs.net/forums/thread/15891.aspx)有一個線程,我正在討論我的Minimax。在這裏,你可以找到我的最新的代碼(http://www.inf.ufrgs.br/~pmdusso/works/Functional_Implementation_Minimax_FSharp.htm

由於提前,

佩德羅Dusso

嗯,我明白的很清楚的想法,但我不能使它發揮作用。記住我想從葉子列表(「List.max」:P)中獲得最大靜態值的葉子,我認爲實施CompareToEquals會讓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',當我嘗試ALT時,輸入此消息出現在我的F#Interactive中。位置{77,39}對應於mycompare調用的開始(在GetHashCode中)。

我在做什麼錯了?我能做些什麼更好?

非常感謝,

佩德羅Dusso

編輯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" 

感謝您的反饋!

佩德羅Dusso

回答

6

首先,你得到的異常,因爲compare函數調用你比較值(即x.ComaperTo(y))的CompareTo方法。您在CompareTo的自定義實現中使用compare進行比較的值是要求您(通過運行時)比較的值,因此會導致堆棧溢出。

執行CompareToEquals的常用方法是僅比較存儲在類型中的一些值。例如,你可以寫這樣的事情:

編輯:你可以寫一個輔助函數mycopare做比較(或者你可以簡單地改變CompareTo實現)。但是,如果你想使用一個函數,你需要在類型聲明中移動它(以便它知道類型 - 注意在F#中聲明的順序很重要!)

寫入它的一種方法是這樣的:

[<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每次調用需要的數據的只有一些部分,所以你取得一些進展。

+0

嘿,我編輯了我自己的帖子..我不知道這是否是正確的方式給你一個反饋......如果沒有,我可以馬上改變!謝謝,佩德羅·杜索 – 2010-06-22 17:52:39

+0

@Pmdusso:是的,我認爲這是擴展問題的好方法。我更新了我的答案以提供一個更完整的示例 - 您說得對,只是提前(在類型聲明之前)對函數進行分類將不起作用。 – 2010-06-22 21:18:44