تنفيذ المقارنة المخصصة مع CustomComparison و CustomEfection في F# tuple

StackOverflow https://stackoverflow.com/questions/3093408

سؤال

أنا هنا لأطلب موضوعًا محددًا - لقد وجدت حقًا بعض المعلومات حول هذا الموضوع على الويب. أنا أقوم بتنفيذ إصدار F# من خوارزمية Minimax. المشكلة التي أواجهها الآن هي أنني أريد مقارنة ورقة الشجر (بنية البيانات أدناه). البحث عن erros أعطاه VS لي وصلت إلى شيء من هذا القبيل:

نوع الشجرة الذي اعتدت أن يكون لدي:

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"

في النهاية ، أريد فقط الحصول على الحد الأقصى (و MIN) لقائمة من 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) مع أناقش الحد الأدنى الخاص بي. هنا يمكنك العثور على آخر رمز لي (http://www.inf.ufrgs.br/~pmdusso/works/functional_implementation_minimax_fsharp.htm)

شكرا مقدما،

بيدرو دوسو

حسنًا ، لقد فهمت الفكرة بوضوح تامة ، لكنني لا أستطيع أن أجعلها تعمل. أتذكر أنني أريد الحصول على الورقة ذات القيمة الساكنة القصوى من قائمة الأوراق ("list.max": p) ، أعتقد أن تطبيق CompareTo أو Equals هل ستدع القائمة. 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 Red-Underlined)

2) (77،39): خطأ FS0039: لا يتم تعريف القيمة أو المنشئ "MyCompare" ، عندما أحاول ظهور هذه الرسالة تظهر في F# التفاعلية. يتوافق الموضع {77،39} مع بداية مكالمة MyCompare (في GethashCode).

ماذا أفعل خطأ؟ ماذا يمكنني أن أفعل بشكل أفضل؟

شكرا جزيلا،

بيدرو دوسو

تحرير 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 الدالة تستدعي CompareTo طريقة القيم التي تقارنها (وهذا هو x.ComaperTo(y)). القيم التي تقارنها باستخدام compare في التنفيذ المخصص لـ CompareTo هي القيم التي يُطلب منك مقارنتها (حسب وقت التشغيل) ، لذلك يؤدي هذا إلى تجاوز الفائض.

الطريقة المعتادة للتنفيذ CompareTo أو Equals هو مقارنة بعض القيم التي تقوم بتخزينها فقط في النوع الخاص بك. على سبيل المثال ، يمكنك كتابة شيء مثل هذا:

تعديل: يمكنك كتابة وظيفة المساعد 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 لا تأخذ سوى جزء من البيانات ، لذلك فأنت تحرز بعض التقدم.

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top