Implementierung eigener Vergleich mit CustomComparison und CustomEquality in F # Tupel
-
29-09-2019 - |
Frage
Ich bin hier, um ein bestimmtes Thema fragen - ich wirklich wenige Informationen über diese im Internet gefunden. Ich bin ein F # Version von Minimax-Algorithmus implementiert. Das Problem, das ich jetzt habe, ist, dass ich Blatt von meinem Baum (Datenstruktur unten) vergleichen möge. Durchsuchen der erros der VS gab mir kam ich zu so etwas wie folgt aus:
Der Baum Typ I verwendet hat:
type TreeOfPosition =
| LeafP of Position
| BranchP of Position * TreeOfPosition list
und die temptative für die Umsetzung der 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"
Am Ende bekommt ich mag nur den max (und die min) aus einer Liste von LeafP durch ihren statischen Wert (calculate in anderer Funktion).
Der obige Code kompiliert. Doch mit dieser Prüfung:
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
habe ich einen System.StackOverflowException in der "|: TreeOfPosition als y -> vergleichen (x) (y)". Zeile in der Überschreibung des GetHashCode
habe ich einen Thread im hubfs.net ( http: //cs.hubfs. net / Foren / thread / 15891.aspx ) mit mir meine Minimax bin zu diskutieren. //www.inf.ufrgs: Hier können Sie meine neuesten Code ( http finden. br / ~ pmdusso / Werke / Functional_Implementation_Minimax_FSharp.htm )
Vielen Dank im Voraus,
Pedro Dusso
Nun, verstand ich sehr deutlich die Idee, aber ich kann es nicht funktioniert. Daran erinnernd, dass ich das Blatt mit dem maximalen statischen Wert aus einer Liste von Blättern ( „List.max“: P) erhalten will, denke ich, die CompareTo
oder Equals
Umsetzung werde die List.max arbeitet an sie, zu korrigieren lassen?
Ich komponiere die Dinge wie diese:
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"
Die Probleme, das ich habe, die Funktionen auf diese Weise der Anordnung ist:
1) Der Muster-Diskriminator 'LeafP' nicht definiert ist (mit LeafP rot unterstrichen)
2) (77,39): Fehler FS0039: Der Wert oder Konstruktor 'mycompare' ist nicht definiert, wenn ich versuche, ein ALT Diese Nachricht in meinem F # Interactive erscheint ENTER. Die Position {77,39} entspricht den Anfang mycompare Aufruf (in GetHashCode).
Was mache ich falsch? Was kann ich besser machen?
Vielen Dank,
Pedro Dusso
EDIT 3 - Gelöst
Ja! Ich schaffe Ihre Antwort auf Arbeit finaly!
Der letzte Code ist hier:
[<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"
Danke für das Feedback!
Pedro Dusso
Lösung
Zunächst einmal, Sie bekommen die Ausnahme, da die compare
Funktion die CompareTo
Methode des Wertes rufen Sie vergleicht (der x.ComaperTo(y)
ist). Die Werte, die Sie verwenden compare
in der benutzerdefinierten Implementierung von CompareTo
Vergleich sind die Werte, die Sie gefragt werden, vergleichen (von der Laufzeit), so dass dieser den Stapelüberlauf verursacht.
Der üblicher Weg CompareTo
oder Equals
zu implementieren, ist nur einige Werte zu vergleichen, dass Sie in Ihrer Art speichern. Zum Beispiel könnte man so etwas schreiben:
Bearbeiten : Sie können eine Hilfsfunktion mycopare
schreiben den Vergleich zu tun (oder man könnte einfach die CompareTo
Implementierung ändern). Wenn Sie jedoch eine Funktion verwenden möchten, müssen Sie es in der Typdeklaration bewegen (so dass es über den Typ weiß - beachten Sie, dass in F #, die Reihenfolge der Deklaration Sachen)
Eine Möglichkeit, es zu schreiben, ist dies:
[<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"
Das würde funktionieren, weil jeder Anruf zu compare
nur einen Teil der Daten übernimmt, so dass Sie einige Fortschritte machen.