Domanda

Sono qui per chiedere a un argomento specifico - ho davvero trovato poche informazioni su questo sul web. Sto implementando una versione F # dell'algoritmo Minimax. Il problema che sto avendo ora è che voglio mettere a confronto Foglia del mio albero (struttura dei dati di seguito). Cercando le erros VS ha dato a me sono arrivato a qualcosa di simile:

Il tipo di albero che ho usato per avere:

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

e il temptative per l'attuazione 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"

Alla fine, voglio solo ottenere il massimo (e la min) di un elenco di LeafP dal suo valore statico (calcolare in altra funzione).

Il codice sopra compila. Tuttavia il test con questo:

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

Ho una System.StackOverflowException nel "|:? TreeOfPosition come y -> confrontare (x) (y)". Riga l'override del GetHashCode

Ho un thread nel hubfs.net ( http: //cs.hubfs. / forum / thread net / 15891.aspx ) con sto discutendo il mio Minimax. Qui potete trovare il mio codice di lastest ( http: //www.inf.ufrgs. br / ~ pmdusso / opere / Functional_Implementation_Minimax_FSharp.htm )

Grazie in anticipo,

Pedro Dusso

Bene, ho capito molto chiaramente l'idea, ma non riesco a farlo funzionare. Ricordando che voglio ottenere la foglia con il valore massimo da un elenco statico di foglie ( “List.max”: P), penso che l'attuazione del CompareTo o Equals farà si che il List.max lavora su di loro, giusto? Compongo le cose in questo modo:

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" 

I problemi che sto avendo organizzando le funzioni in questo modo è:

1) Il pattern discriminatore 'LeafP' non è definito (con LeafP rosso-sottolineato)

2) (77,39): l'errore FS0039: Il valore o il costruttore 'mycompare' non è definito, quando provo un ALT INVIO questo messaggio appare nella mia F # Interactive. La posizione {77,39} corrisponde all'inizio della chiamata mycompare (in GetHashCode).

Quello che sto facendo di sbagliato? Cosa posso fare di meglio?

Grazie mille,

Pedro Dusso

EDIT 3 - Risolto

Sì! Riesco la tua risposta al lavoro finalmente!

Il codice finale è qui:

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

Grazie per il feedback!

Pedro Dusso

È stato utile?

Soluzione

Prima di tutto, stai diventando l'eccezione poiché la funzione compare chiama il metodo CompareTo dei valori si sta confrontando (che è x.ComaperTo(y)). I valori si sta confrontando con compare nella realizzazione personalizzata di CompareTo sono i valori che la viene chiesto di confrontare (dal runtime), quindi questo fa sì che l'overflow dello stack.

Il solito modo per implementare CompareTo o Equals è quello di confrontare solo alcuni valori che si memorizzare nel vostro tipo. Ad esempio, si potrebbe scrivere qualcosa di simile:

Modifica : È possibile scrivere una funzione di supporto mycopare per fare il confronto (o si può semplicemente cambiare l'implementazione CompareTo). Tuttavia, se si desidera utilizzare una funzione, è necessario spostare all'interno della dichiarazione del tipo (in modo che conosce il tipo - Si noti che in F #, l'ordine delle questioni dichiarazione)

Un modo di scrivere è questo:

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

Questo potrebbe funzionare, perché ogni chiamata a compare richiede solo una parte dei dati, in modo che stai facendo qualche progresso.

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top