سؤال

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

data MidiMessage = MidiMessage !Int !MidiMessage
هل كانت مفيدة؟

المحلول

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

data Foo = Foo Int Int !Int !(Maybe Int)

f = Foo (2+2) (3+3) (4+4) (Just (5+5))

الوظيفة f أعلاه، عند تقييمها، ستعود "Thunk": أي رمز التنفيذ لمعرفة قيمته. في تلك المرحلة، لا توجد فو حتى الآن، فقط الرمز.

ولكن في مرحلة ما، قد يحاول شخص ما أن ننظر داخله، وربما من خلال مباراة نمط:

case f of
     Foo 0 _ _ _ -> "first arg is zero"
     _           -> "first arge is something else"

هذا سوف ينفذ كود كاف للقيام بما يحتاجه، وليس أكثر. لذلك سيخلق Foo مع أربعة معلمات (لأنك لا تستطيع أن تنظر داخلها دون ذلك). الأول، لأننا نختبرها، نحن بحاجة إلى تقييم كل الطريق إلى 4, ، حيث ندرك أنه لا يتطابق.

الثانية لا يحتاج إلى تقييمها، لأننا لا نختبرها. وهكذا، بدلا من 6 يجري تخزينها في موقع الذاكرة هذا، سنقوم بتخزين التعليمات البرمجية للتقييم المحتمل لاحقا، (3+3). وبعد سوف تتحول إلى 6 فقط إذا نظر شخص ما في ذلك.

المعلمة الثالثة، ومع ذلك، لديه ! أمامها، لذلك يتم تقييمه بدقة: (4+4) يتم تنفيذها، و 8 يتم تخزينه في موقع الذاكرة هذا.

المعلمة الرابعة يتم تقييمها بدقة. ولكن هنا حيث يحصل صعبة بعض الشيء: نحن نقيم غير كاملا، ولكن فقط لضعف شكل الرأس العادي. هذا يعني أننا معرفة ما إذا كان ذلك Nothing أو Just شيء ما، وتخزين ذلك، لكننا لا نذهب إلى أبعد من ذلك. هذا يعني أننا نقوم بتخزين Just 10 ولكن في الواقع Just (5+5), ، تاركة thunk داخل غير متوفرة. من المهم أن تعرف ذلك، على الرغم من أنني أعتقد أن جميع الآثار المترتبة على هذا تتجاوز نطاق هذا السؤال إلى حد ما.

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

f x !y = x*y

f (1+1) (2+2) سوف ترجع thunk (1+1)*4.

نصائح أخرى

طريقة بسيطة لرؤية الفرق بين حجج البناء الصارمة وغير الصارمة هي الطريقة التي يتصرف بها عندما تكون غير محددة. منح

data Foo = Foo Int !Int

first (Foo x _) = x
second (Foo _ y) = y

منذ الحجة غير الصارمة غير تقييمها second, ، المرور في undefined لا يسبب مشكلة:

> second (Foo undefined 1)
1

لكن الحجة الصارمة لا يمكن أن تكون undefined, ، حتى لو لم نستخدم القيمة:

> first (Foo 1 undefined)
*** Exception: Prelude.undefined

أعتقد أنه شروح صارمة.

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

هناك مزيد من المعلومات حول هذه الصفحة: الأداء / الصرامة.

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