سؤال

وأريد أن تعزيز نمط لمطابقة أرقام فقط التي تمر وظيفة التحقق من صحة إضافية.

let (|IsValid|_|) n = ...

let (|Nil|One|Two|) (l : int list) =
    match l with 
    | a :: b :: t -> Two(a + b)
    | a :: t      -> One(a)
    | _           -> Nil

وهذه القضية 'واحد' من السهل:

    | IsValid(a) :: t -> One(a)

وهذه القضية "اثنان" ليست واضحة بالنسبة لي. انها تحتاج للتحقق من مجموع الأرقام. يمكنني أن أفعل هذا دون استخدام عند الحرس؟

...

وتحرير: I يمكن استخدام عندما الحرس (مع وظيفة isValid العائدين منطقي) مثل هذا:

    | a :: b :: t when isValid a + b -> Two(a + b)

وهذا هو أقل أناقة من مجرد مطابقة نمط. الأسوأ من ذلك، يتم تطبيق ب + مرتين.

لاحظ أيضا وهذا هو نسخة مبسطة من قانون بلدي الفعلي (أنا لا أسعى لمباراة ببساطة ضد أطوال مختلفة من القائمة على سبيل المثال) - السؤال هو حول مطابقة متداخلة على نمط سلبيات مزدوج.

هل كانت مفيدة؟

المحلول

وبلدي الحل: إضافة "المساعد" recogniser مع قيمة إرجاع مصممة لاستخدامها في نمط الأم:

let (|MatchTwo|_|) = function
    | a :: b :: t -> Some(a + b :: t)
    | _ -> None

واستخدامه مثل ذلك:

let (|Nil|One|Two|) (l : int list) =
    match l with 
    | MatchTwo(IsValid(a) :: t) -> Two(a)
    |          IsValid(a) :: t  -> One(a)
    | _                         -> Nil

نصائح أخرى

وعند القيام:

| a :: b :: t -> ... 

وأنت ليس بالضرورة مطابقة العنصرين في القائمة. فمن الأفضل لاستخدام [] بدلا من t لتتناسب مع عنصرين بالضبط --t يمكن أن تكون قائمة أكثر العناصر.

 | a :: b :: [] -> Two (a+b)

وهذا سيضمن أن كنت مطابقة اثنين وعنصرين فقط --error فحص مجانا! أقترح القيام بذلك حتى ولو كنت تتوقع وظيفة لقبول سوى قائمة من 0 أو 1 أو 2 العناصر. لذا،

تحرير:

let (|MatchTwo|_|) = function
    | a :: b :: t -> Some(a + b :: t)
    | _ -> None
let (|Nil|One|Two|) (l : int list) = match l with 
    | MatchTwo(IsValid(a) :: t) -> Two(a)
    | IsValid(a) :: t  -> One(a)
    | _ -> Nil

نعم، استخدم when. هذه فوضى. نمط مطابقة ليست سوى ذلك، وتطبيق وظائف في المباراة حقا لا معنى له. ولكن تأخذ في الاعتبار ما ذكرته قبل. وبناء على المثال الخاص بك:

match l with
| a :: b :: t when isValid (a+b) -> Two (a+b)
| a :: t when isValid (a) -> One a
| _ -> Nil

والنمط الثاني سوف تتطابق قوائم طول أطول ثم واحد إذا isValid هي كاذبة عن النمط الأول --be حذر. أن تكون محددة في أنماط الخاص بك ممكن، إذا كنت تقصد لتتناسب مع عنصر واحد، أن تفعل ذلك.

إذا مهما العملية التي تستخدم للجمع بين أ و ب (في هذه الحالة +) ومكلفة حسابيا، ثم سيكون لديك لإسقاط when واستخدام عبارة اسمحوا قبل اختبار isValid وإعادة نوع متغير.

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