La implementación de comparación personalizada con CustomComparison y CustomEquality en Fa # tupla

StackOverflow https://stackoverflow.com/questions/3093408

Pregunta

Estoy aquí para pedir un tema específico - Realmente encontraron información sobre esto en la web. Estoy poniendo en práctica una versión # F del algoritmo Minimax. El problema que estoy teniendo ahora es que quiero comparar la hoja de mi árbol (estructura de datos más adelante). Búsqueda de los erros el VS me dio a mí llegué a algo como esto:

El tipo de árbol que solía tener:

type TreeOfPosition =
    | LeafP   of Position
    | BranchP of Position * TreeOfPosition list

y el temptative para la realización del 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"

Al final, sólo quiero llegar al máximo (y el min) de una lista de LeafP por su valor estático (calcule en función de otra).

El código anterior compila. Sin embargo la prueba con esto:

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

Tengo una System.StackOverflowException en el "|:? TreeOfPosition como Y -> comparar (x) (y)". Línea en la anulación de la GetHashCode

I tiene un hilo en el hubfs.net ( http: //cs.hubfs. / foros / hilo neta / 15891.aspx ) con el que estoy discutiendo mi Minimax. Aquí puede encontrar el código de lastest ( http: //www.inf.ufrgs. br / ~ pmdusso / obras / Functional_Implementation_Minimax_FSharp.htm )

Gracias de antemano,

Pedro Dusso

Bueno, me entiende muy claramente la idea, pero no puedo hacer que funcione. Recordando que quiero conseguir la hoja con el valor estático máximo de una lista de hojas ( “List.max”: P), creo que la aplicación de la CompareTo o Equals permitirá que el List.max trabaja en ellos, ¿verdad? Compongo las cosas como esto:

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" 

Los problemas que tengo la organización de las funciones de esta manera es:

1) El discriminador patrón 'LeafP' no está definido (con LeafP subrayada en rojo)

2) (77,39): error FS0039: El valor o constructor 'mycompare' no está definido, cuando intento una ALT ENTER este mensaje aparece en mi F # interactivo. La posición {77,39} corresponde al comienzo de la llamada mycompare (en GetHashCode).

Lo que estoy haciendo mal? ¿Qué puedo hacer mejor?

Muchas gracias,

Pedro Dusso

EDITAR 3 - Resuelto

Sí! Administro su respuesta al trabajo finaly!

El código final está aquí:

[<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" 

Gracias por los comentarios!

Pedro Dusso

¿Fue útil?

Solución

En primer lugar, que está recibiendo la excepción ya que la función compare llama al método CompareTo de los valores que se está comparando (que es x.ComaperTo(y)). Los valores que se está comparando el uso de compare en la implementación personalizada de CompareTo son los valores que el se le pide que compare (por el tiempo de ejecución), así que esto hace que el desbordamiento de pila.

La forma más habitual de implementar CompareTo o Equals es comparar sólo algunos valores que se almacenan en su tipo. Por ejemplo, podría escribir algo como esto:

Editar : Puede escribir un mycopare función auxiliar para hacer la comparación (o simplemente podría cambiar la implementación CompareTo). Sin embargo, si desea utilizar una función, es necesario moverlo dentro de la declaración de tipo (para que sepa sobre el tipo - nota de que en C #, el orden de los asuntos de declaración)

Una forma de escribirlo es la siguiente:

[<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" 

Esto funcionaría, ya que cada llamada a compare toma sólo una parte de los datos, por lo que está haciendo algunos progresos.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top