Я здесь для выяснения у определенной темы - я действительно нашел немногих информацией об этом в сети. Я реализую версию F# Минимаксного алгоритма. Проблема, которую я имею теперь, состоит в том, что я хочу сравнить Лист своего дерева (структура данных ниже). При поиске erros, который VS дал мне, я прибыл во что-то вроде этого:
Древовидный тип я раньше имел:
type TreeOfPosition =
| LeafP of Position
| BranchP of Position * TreeOfPosition list
и temptative для реализации IComparable
type staticValue = int
[]
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"
В конце я просто хочу получить макс. (и минута) списка LeafP его статическим значением (вычислите в другой функции).
Код выше компиляций. Однако тестирование с этим:
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
Я получил Систему. StackOverflowException в "|:? TreeOfPosition как y-> выдерживают сравнение (x) (y)" строка в переопределении GetHashCode.
У меня есть поток в hubfs.net (http://cs.hubfs.net/forums/thread/15891.aspx) с, я обсуждаю свой Минимакс. Здесь можно найти мой код lastest (http://www.inf.ufrgs.br/~pmdusso/works/Functional_Implementation_Minimax_FSharp.htm)
Заранее спасибо,
Pedro Dusso
Ну, я понял очень ясно идею, но я не могу заставить ее работать. Запоминание, что я хочу получить лист с макс. статическим значением из списка листов (“List.max” :P), я думаю, реализовывая CompareTo
или Equals
позволит работам List.max над ними, корректный? Я составляю вещи как это:
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"
Проблемы у меня есть расположение функций этот путь:
1) Различитель шаблона 'LeafP' не определяется (с красным подчеркнутым LeafP)
2) (77,39): ошибка FS0039: значение или конструктор 'mycompare' не определяются, когда я пробую ALT, ВХОДЯТ, это сообщение появляются в моем Интерактивном F#. Положение {77,39} соответствует началу вызова mycompare (в GetHashCode).
Что я делаю неправильно? Что я могу добиться большего успеха?
Большое спасибо,
Pedro Dusso
РЕДАКТИРОВАНИЕ 3 - решенный
Да! Я управляю Вашим ответом для работы наконец!
Заключительный код здесь:
[]
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"
Спасибо за обратную связь!
Pedro Dusso
Во-первых, вы получаете исключение, потому что функция compare
вызывает метод CompareTo
сравниваемых значений (то есть x.ComaperTo(y)
). Значения, которые вы сравниваете с помощью compare
в пользовательской реализации CompareTo
, являются значениями, которые вас просят сравнить (во время выполнения), поэтому это вызывает переполнение стека.
Обычный способ реализации CompareTo
или Equals
заключается в сравнении только некоторых значений, которые вы храните в вашем типе. Например, вы можете написать что-то вроде этого:
EDIT: Вы можете написать вспомогательную функцию mycopare
для выполнения сравнения (или вы можете просто изменить реализацию CompareTo
). Однако, если вы хотите использовать функцию, вам нужно поместить ее внутрь объявления типа (чтобы она знала о типе - обратите внимание, что в F# порядок объявления имеет значение!)
Один из вариантов записи выглядит так:
[<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"
Это будет работать, потому что каждый вызов compare
занимает только часть данных, так что вы делаете некоторый прогресс.