Реализация пользовательского сравнения с CustomComparison и CustomEquality в кортеже F#

Я здесь для выяснения у определенной темы - я действительно нашел немногих информацией об этом в сети. Я реализую версию 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

9
задан Pedro Dusso 22 June 2010 в 10:17
поделиться

1 ответ

Во-первых, вы получаете исключение, потому что функция 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 занимает только часть данных, так что вы делаете некоторый прогресс.

7
ответ дан 3 November 2019 в 04:40
поделиться
Другие вопросы по тегам:

Похожие вопросы: