F #: تحذير FS0020: يجب أن يكون لهذا التعبير نوع "وحدة"، ولكن لديه نوع "Bool"
سؤال
أحاول تعلم 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