在F#元组中实施自定义比较和CustomeQuality
-
29-09-2019 - |
题
我在这里问一个特定的主题 - 我真的在网络上找到了有关此的信息。我正在实现Minimax算法的F#版本。我现在遇到的问题是我想比较树的叶子(下面的数据结构)。在搜索VS给我的传播中,我到达了这样的事情:
我以前有的树类型:
type TreeOfPosition =
| LeafP of Position
| BranchP of Position * TreeOfPosition list
以及实施显着的诱惑
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
我在“ |:?treeofposition as y->“ y-> compare(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)
提前致谢,
佩德罗·杜斯索(Pedro Dusso)
好吧,我非常清楚地理解了这个想法,但我无法使它起作用。记住我想从叶子列表(“ list.max”:p)中获得最大静态值的叶子,我认为实现 CompareTo
或者 Equals
会让列表。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)未定义模式鉴别'叶''
2)(77,39):错误fs0039:当我尝试ALT输入时,未定义值或构造函数“ myCompare”,该消息将显示在我的f#Interactive中。位置{77,39}对应于MyCompare Call的开头(在GethashCode中)。
我在做什么错?我能做得更好吗?
非常感谢,
佩德罗·杜斯索(Pedro 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"
感谢您的反馈!
佩德罗·杜斯索(Pedro Dusso)
解决方案
首先,您会得到例外,因为 compare
函数调用 CompareTo
您要比较的值的方法(即 x.ComaperTo(y)
)。您要比较的值 compare
在自定义实施中 CompareTo
是要求您比较的值(通过运行时),因此会导致堆栈溢出。
实施的通常方法 CompareTo
或者 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
仅获取一部分数据,因此您正在取得一些进展。