2010-06-22 44 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