Implementando comparação personalizada com CustomComparison e CustomEquality em tupla F #
Estou aqui para perguntar um tópico específico - encontrei realmente poucas informações sobre isso na web. Estou implementando uma versão F # do algoritmo Minimax. O problema que estou tendo agora é que quero comparar o Leaf da minha árvore (estrutura de dados abaixo). Pesquisando os erros que o VS me deu, cheguei a algo assim:
O tipo de árvore que eu costumava ter:
type TreeOfPosition =
| LeafP of Position
| BranchP of Position * TreeOfPosition list
e o tentador de implementar o 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"
No final, eu só quero obter o máximo (e o mínimo) de uma lista de LeafP pelo seu valor estático (calcular em outra função).
O código acima é compilado. No entanto, testando com isso:
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
Eu recebi um System.StackOverflowException na linha "|:? TreeOfPosition como y -> compare (x) (y)" na substituição do GetHashCode.
Eu tenho um thread no hubfs.net (http://cs.hubfs.net/forums/thread/15891.aspx) com estou discutindo meu Minimax. Aqui você pode encontrar meu último código (http://www.inf.ufrgs.br/~pmdusso/works/Functional_Implementation_Minimax_FSharp.htm)
Desde já, obrigado,
Pedro Dusso
Bem, eu entendi muito claramente a idéia, mas não posso fazê-la funcionar. Lembrando que quero obter a folha com o valor estático máximo de uma lista de folhas (“List.max”: P), acho que implementar oCompareTo
ouEquals
vai deixar o List.max funcionar neles, correto? Eu componho coisas assim:
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"
Os problemas que estou tendo ao organizar as funções dessa maneira são:
1) O discriminador de padrões 'LeafP' não está definido (com LeafP sublinhado em vermelho)
2) (77,39): erro FS0039: O valor ou o construtor 'mycompare' não está definido. Quando tento ALT ENTER, essa mensagem aparece no meu F # Interactive. A posição {77,39} corresponde ao início da minha chamada de comparação (em GetHashCode).
O que estou fazendo de errado? O que posso fazer melhor?
Muito obrigado,
Pedro Dusso
EDIT 3 - Resolvido
Sim! Eu administro sua resposta para trabalhar finalmente!
O código final está aqui:
[<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"
Obrigado pelo feedback!
Pedro Dusso