11

我来这里是为了问一个特定的话题——我真的在网上找到了一些关于这个的信息。我正在实现 F# 版本的 Minimax 算法。我现在遇到的问题是我想比较我的树的叶子(下面的数据结构)。搜索 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 ) 中有一个线程,我正在讨论我的 Minimax。在这里你可以找到我最新的代码(http://www.inf.ufrgs.br/~pmdusso/works/Functional_Implementation_Minimax_FSharp.htm

提前致谢,

佩德罗·杜索

好吧,我非常清楚这个想法,但我无法让它发挥作用。记住我想从叶子列表(“List.max”:P)中获取具有最大静态值的叶子,我认为实现CompareToorEquals会让 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 ENTER 时,此消息出现在我的 F# Interactive 中。位置 {77,39} 对应于 mycompare 调用的开始(在 GetHashCode 中)。

我做错了什么?我能做些什么更好?

非常感谢,

佩德罗·杜索

编辑 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函数调用了CompareTo您正在比较的值的方法(即x.ComaperTo(y))。您compare在自定义实现中CompareTo使用的值是您被要求比较的值(由运行时),因此这会导致堆栈溢出。

实现CompareToor的常用方法Equals是仅比较您存储在类型中的一些值。例如,你可以这样写:

编辑:您可以编写一个辅助函数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只需要部分数据,所以你正在取得一些进展。

于 2010-06-22T13:27:54.570 回答