سؤال

لقد كتبت وظيفة Haskell التي تحسب مصنفة كل رقم في قائمة معينة وتطبعها على الشاشة.

factPrint list =
if null list
    then putStrLn ""
    else do putStrLn ((show.fact.head) list)
        factPrint (tail list)

تعمل الوظيفة ، لكنني أجد السطر الثالث مربكًا بعض الشيء. لماذا لم يبلغ المترجم (GHC) عن خطأ فيه نظرًا لعدم وجود "فعل" قبل وظيفة "putstrln" (شبه؟)؟ إذا حذفت "تفعل" من السطر الرابع ، فإن الخطأ يبرز كما هو متوقع.

أنا جديد تمامًا على Haskell وطرقه ، لذا يرجى العفو عني إذا قلت شيئًا سخيفًا للغاية.

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

المحلول

do putStrLn ((show.fact.head) list)
   factPrint (tail list)

هو في الواقع طريقة أخرى للكتابة

putStrLn ((show.fact.head) list) >> factPrint (tail list)

وهو ما يعني بدوره

putStrLn ((show.fact.head) list) >>= \_ -> factPrint (tail list)

ال do التدوين هو وسيلة مريحة لتوصيل هذه الموناد معًا ، بدون هذا الجملة القبيحة الأخرى.

إذا كان لديك بيان واحد فقط داخل do, ، فأنت لا تربط أي شيء معًا ، و do زائد.

نصائح أخرى

إذا كنت جديدًا على Haskell ، فكر في do على غرار الأقواس المطلوبة بعد if في لغة تشبه C:

if (condition)
  printf("a"); // braces not required
else {
  printf("b"); // braces required
  finish();
}

do يعمل بنفس الطريقة في هاسكل.


ربما سيساعد ذلك في النظر إلى نوع الحقائق ، ثم Refactor لاستخدام مطابقة الأنماط:

factPrint :: [Int] -> IO ()
factPrint [] = putStrLn ""
factPrint list = do
  putStrLn (show.fact.head) list
  factPrint (tail list)

لذلك ، إذا عادت الحقائق IO (), ، ونوع putStrLn "" هو IO (), ، ثم من القانوني تمامًا factPrint [] لتساوي putStrLn "". رقم do مطلوب-في الواقع ، يمكنك القول فقط factPrint [] = return () إذا كنت لا تريد خط جديد.

do يستخدم لربط تعبيرات أحادية متعددة معا. ليس له أي تأثير عندما يتبعه تعبير واحد فقط.

من أجل أن تكون جيدًا ، فمن الضروري فقط أن يكون للباقي والباقي الآخر نفس النوع. لأن كلا الجملتين لهما النوع IO () هذا هو الحال.

يتم استخدام الكلمة الرئيسية DO للتسلسل ، لا يجب أن تحتوي على if-then-else في Haskell do على الإطلاق إذا كان كل فرع عبارة عن بيان واحد على سبيل المثال.

if a
  then b
  else c

أنت بحاجة إلى do في المثال الخاص بك وأنت تتسلسل عمليتين على فرع آخر. إذا حذفت do ثم factPrint(tail list) يعتبر البيان جزءًا من الوظيفة ، وبالتالي يشكو المترجم لأنه واجه بيانًا غير متوقع.

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