F #: تحذير FS0020: يجب أن يكون لهذا التعبير نوع "وحدة"، ولكن لديه نوع "Bool"

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

  •  12-09-2019
  •  | 
  •  

سؤال

أحاول تعلم F # من خلال الذهاب من خلال بعض مشاكل Euler ووجدت مشكلة لم أتمكن من معرفة ذلك. هذا هو الحل الساذج.

let compute =
    let mutable f = false
    let mutable nr = 0
    while f = false do
        nr <- nr + 20
        f = checkMod nr
    nr

عندما أقوم بذلك، أحصل على رسالة الخطأ تحذير FS0020: يجب أن يحتوي هذا التعبير على نوع "وحدة"، ولكن لديه نوع "BOOL" على التعبير "NR <- NR +20". لقد حاولت إعادة كتابة وإحرار التعبيرات حولها وأحصل دائما على هذا الخطأ على الخط أدناه في حين بيان.

أنا أكتب هذا باستخدام Beta vs2010.

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

المحلول

السطر التالي:

f = checkMod nr

هو فحص المساواة، وليس مهمة كما أعتقد أنك تنوي. تغييره إلى:

f <- checkMod nr

وكلها يجب أن تعمل بشكل جيد. لست متأكدا من السبب في أنك استخدمت بناء الجملة الصحيح على السطر السابق وليس هذا الخط ...

أيضا، الخط while f = false do يجب أن تكون مبسطة حقا while not f do; ؛ الشيكات المساواة على المنطاقين هي التوظيف إلى حد ما.

نظرا لأنني مذكرة جانبية، أشعر بالحاجة إلى الإشارة إلى أنك تحاول بفعالية استخدام F # بلغة حتمية. استخدام متغيرات قابلية القابلة للتغيير وفي حين يتم تثبيط الحلقات بشدة في اللغات الوظيفية (بما في ذلك F #)، خاصة عند وجود حل عملي (وأبسط (أبسط)، كما هو الحال في هذا الموقف. أوصي بقراءة بعض البرمجة في النمط الوظيفي. بالطبع، فقط الحصول على السيطرة مع بناء الجملة هو شيء مفيد في حد ذاته.

نصائح أخرى

نظرا لأنني أستطيع أن أتخيل صفحة WEG هذه أصبحت مكان "الكنسي" للبحث عن معلومات حول تحذير FS0020., ، إليك الملخص السريع الخاص بي في الحالات الثلاثة الأكثر شيوعا التي تحصل عليها، وكيفية إصلاحها.

تجاهل عمدا نتيجة وظيفة تسمى فقط لتأثيراتها الجانبية:

// you are calling a function for its side-effects, intend to ignore result    
let Example1Orig() =
    let sb = new System.Text.StringBuilder()
    sb.Append("hi")       // warning FS0020
    sb.Append(" there")   // warning FS0020
    sb.ToString()

let Example1Fixed() =
    let sb = new System.Text.StringBuilder()
    sb.Append("hi") |> ignore
    sb.Append(" there") |> ignore
    sb.ToString()

تحذير مفيد، مشيرا إلى وجود خطأ (وظيفة لا يوجد لديه تأثيرات):

// the warning is telling you useful info 
// (e.g. function does not have an effect, rather returns a value)
let Example2Orig() =
    let l = [1;2;3] 
    List.map (fun x -> x * 2) l    // warning FS0020
    printfn "doubled list is %A" l

let Example2Fixed() =
    let l = [1;2;3] 
    let result = List.map (fun x -> x * 2) l
    printfn "doubled list is %A" result

مشغل التعيين المربك ومشغل مقارنة المساواة:

// '=' versus '<-'
let Example3Orig() =
    let mutable x = 3
    x = x + 1          // warning FS0020
    printfn "%d" x    

let Example3Fixed() =
    let mutable x = 3
    x <- x + 1
    printfn "%d" x    

إذا كنت تحاول اعتماد النمط الوظيفي، فحاول تجنب قيم التبلور.

على سبيل المثال مثل هذا:

let nr =
   let rec compute nr =  
      if checkMod nr then nr else compute (nr + 20)
   compute 0     

while التعبيرات في F # خذ القليل من التعود إذا كنت قادما من لغة حتمية. كل سطر في while التعبير يجب أن يقيم ل unit (فكر في void من C ++ / C #). التعبير الشامل ثم يقيم أيضا ل unit.

في المثال:

nr <- nr + 20

يقيم إلى unit بينما

f = checkMod nr

يقيم إلى أ bool كما noldorin. وأشار. ينتج عن هذا رسالة تحذيرية. يمكنك بالفعل تحويل التحذير إذا كنت ترغب في ذلك. فقط ضع ما يلي في الجزء العلوي من ملفك:

#nowarn "0020"

لقد كنت برمجة في أسلوب حتمي لفترة طويلة، لذلك تعتاد على عقلية البرمجة الوظيفية استغرق بعض الوقت.

في مثالك، تحاول أن تجد أول مضاعف من 20 يمر اختبار الشيكد الخاص بك. هذا هو ماذا او ما جزء. للعملية الوظيفية كيف جزء، أوصي بالتصفح من خلال الأساليب المتاحة للتسلسلات. ما تحتاجه هو العنصر الأول من تسلسل (مضاعفات 20) يمر الاختبار الخاص بك، مثل هذا:

let multi20 = Seq.initInfinite (fun i -> i*20)
let compute = multi20 |> Seq.find checkMod

الأول اسمح بإنشاء قائمة لا حصر لها من twytyplets (لقد قمت بذلك لأعلى). الثاني والسماح للعثور على الرقم الأول في القائمة المذكورة التي تمر الاختبار الخاص بك. مهمتك هي التأكد من أنه يوجد بالفعل رقم من شأنه أن يمر الاختبار، ولكن هذا بالطبع ينطبق أيضا على القانون الحتمي.

إذا كنت ترغب في تكثيف خطين أعلاه في واحد، يمكنك أيضا الكتابة

let computeCryptic = Seq.initInfinite ((*) 20) |> Seq.find checkMod

ولكن أجد أن سحب الأعمال المثيرة من هذا القبيل يمكن أن يؤدي إلى صداع عند محاولة قراءته بعد بضعة أسابيع.

وبنفس الروح مثل منشور براين، إليك طريقة أخرى للحصول على تحذير FS0020: باختصار، أقوم بطريق الخطأ درجات الحجج الوظيفة.

كونه مؤخرا، كان لدي صعوبة في تصحيح التعليمات البرمجية أدناه، والتي بالنسبة للسطر الثاني (دع الناتج المحلي الإجمالي ...) أعطت تحذير FS0020: يجب أن يكون هذا التعبير نوع "وحدة"، ولكن لديه نوع "(سلسلة -> ^ A -> وحدة) * سلسلة * تعويم ". اتضح أن هذا الخط لم يكن هو المشكلة على الإطلاق؛ بدلا من ذلك، كان الخط printfn الذي تم افساليه. إزالة فواصل الفاصلة من قائمة الحجة تم إصلاحها.

for country in wb.Regions.``Arab World``.Countries do
  let gdp = country.Indicators.``GDP per capita (current US$)``.[2010]
  let gdpThous = gdp / 1.0e3
  printfn "%s, %s (%.2f)" country.Name, country.CapitalCity, gdpThous
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top