2010-06-22 4 views
8

특정 주제를 묻기 위해 왔습니다. 웹에서이 주제에 대한 정보는 거의 없습니다. Minimax 알고리즘의 F # 버전을 구현 중입니다. 지금 가지고있는 문제는 내 나무의 잎 (아래의 자료 구조)을 비교하고 싶다는 것입니다. 은 VS 나에게 준하는 오류를 검색 나는 이런 식으로 뭔가에 도착 :F # 튜플의 CustomComparison 및 CustomEquality를 사용한 사용자 정의 비교 구현

내가 사용하는 나무의 유형이합니다 :

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

과에서에서 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" 

을 구현하기위한 temptative을 끝으로, 나는 그 정적 값 (다른 함수에서 계산)에 의해 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 

이 난에 System.StackOverflowException있어 "| : Y로 TreeOfPosition -> (X) (Y) 비교"GetHashCode는의 재정에 줄을.

hubfs.net (http://cs.hubfs.net/forums/thread/15891.aspx)에 스레드가 있습니다. 내 Minimax에 대해 이야기하고 있습니다. 여기에 당신이 내 최신 코드 (http://www.inf.ufrgs.br/~pmdusso/works/Functional_Implementation_Minimax_FSharp.htm) 사전에

감사합니다,

페드로 Dusso

음을 찾을 수 있습니다, 나는 매우 명확하게 아이디어를 이해하지만 그것이 작동 할 수 없습니다. leafs ("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 ENTER를 시도하면 내 F # Interactive에이 메시지가 나타납니다. 위치 {77,39}는 (GetHashCode의) 내 보완 호출의 시작에 해당합니다.

내가 뭘 잘못하고있어? 내가 더 잘할 수 있을까?

정말 감사합니다,

페드로 Dusso

EDIT 3 - 해결

예! 나는 당신의 대답을 최종적으로 관리합니다!

마지막 코드는 여기에 있습니다 : 피드백에 대한

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

감사합니다!compare 기능을 사용하면 비교하는 값 (즉, x.ComaperTo(y)이다)의 CompareTo 메소드를 호출하기 때문에 모든

페드로 Dusso

답변

6

첫째, 당신은 예외가 있어요. CompareTo의 사용자 지정 구현에서 compare을 사용하여 비교하는 값은 런타임에서 비교할 것인지 묻는 값이므로 스택 오버플로가 발생합니다.

CompareTo 또는 Equals을 구현하는 일반적인 방법은 유형에 저장 한 일부 값만 비교하는 것입니다.

편집 : 예를 들어, 다음과 같이 쓸 수 있습니다 당신은 비교를 할 수있는 도우미 함수 mycopare를 작성할 수 (또는 단순히 CompareTo 구현을 변경할 수 있습니다). 그러나 함수를 사용하려면 형식 선언 안에서이 함수를 이동해야합니다 (형식에 대해 알 수 있도록 - F #에서 선언 순서가 중요 함을 유의하십시오).

작성 방법 중 하나는 다음과 같습니다. 이 : compare 호출 할 때마다 데이터의 일부를 필요하기 때문에

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

이 작동 것이다, 그래서 당신은 어떤 진전을 보이고 있습니다.

+0

이봐, 나는 내 자신의 글을 편집 했어. 이것이 너에게 피드백을 줄 수있는 올바른 방법인지 나는 모른다. 그렇지 않다면, 나는 즉시 바뀔 수있다! 고마워, Pedro Dusso –

+0

@Pmdusso : 예, 이것이 질문을 연장하는 좋은 방법이라고 생각합니다. 보다 완벽한 예제를 제공하기 위해 필자의 대답을 업데이트했습니다. 즉, 타입 선언 이전에 함수를 미리 delcaring하는 것만으로는 효과가 없습니다. –