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

questionAnswers(1)

yourAnswerToTheQuestion