كيفية كتابة دالة haskell بدون IO في النوع sig عن طريق إخفاء تغييرات "الحالة".

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

سؤال

لقد كتبت دالة في haskell تأخذ بعض المعلمات مثل Word32 وString (تجاهل الكاري) ومخرجات IO Word32.الآن، هذا هو وظيفة بالمعنى الحقيقي: بالنسبة لنفس المدخلات، سيكون الإخراج هو نفسه دائمًا.ليس هناك أي آثار جانبية.السبب وراء إرجاع الدالة IO Word32 بدلاً من Word32 هو أن الوظيفة تقوم بتحديث العديد من مسجلات تحويل التغذية المرتدة الخطية 32 بت (lfsr) والسجلات الأخرى عدة مرات في حلقة من أجل حساب إخراج Word32 النهائي.

سؤالي هو هذا:مع العلم أن هذه الوظيفة بشكل فعال ليس له أي آثار جانبية, هل من الممكن إخفاء تحديثات التسجيل هذه داخل تنفيذ الوظيفة بحيث تقوم الوظيفة بإرجاع Word32 وليس IO Word32؟إذا كان الأمر كذلك، كيف؟

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

المحلول

نعم!يستطيع هاسكل أن يفعل هذا.

موناد ST

إذا كنت تستخدم بالفعل حالة (سجلات) قابلة للتغيير، وهي مخفية تمامًا عن المراقب خارج الوظيفة، فأنت في حالة موناد ST, ، موناد لتأثيرات الذاكرة فقط.تدخل عالم ST عبر runST, ، وعند الخروج من الوظيفة، يتم ضمان عدم ظهور جميع التأثيرات.

إنها بالضبط البيئة الحسابية المناسبة للعمل مع الحالة المحلية القابلة للتغيير.

الحالة الوظيفية البحتة:الدولة موناد

ومع ذلك، إذا كنت لا تقوم فعليًا بتغيير السجلات أو الخلايا، بل تقوم بتحديث قيمة وظيفية بحتة عدة مرات، فستتوفر بيئة أبسط: الدولة موناد.وهذا لا يسمح بحالة قابلة للتغيير، ولكنه يعطي وهمًا بالحالة المحلية.

IO وunsafePerformIO

أخيرًا، إذا كان لديك تأثيرات محلية قابلة للتغيير، كما هو الحال في ST monad، ولكن لسبب أو لآخر، ستحتاج إلى عمليات الإدخال والإخراج في تلك الحالة (على سبيل المثال عبر مكالمة FFI)، يمكنك محاكاة ST monad، مع نفس القدر من الأمان تقريبًا، باستخدام unsafePerformIO, ، بدلاً من runST, ، لتقديم بيئة الإدخال والإخراج المحلية.نظرًا لأن IO monad لا يحتوي على أنواع جيدة لفرض التجريد، فسوف تحتاج إلى التأكد يدويًا من أن الآثار الجانبية لن تكون ملحوظة.

نصائح أخرى

إذا قمت باستيراد هذه الوظيفة باستخدام FFI، فما عليك سوى إزالة ملف IO من نوع الإرجاع.وإلا استخدم unsafePerformIO :: IO a -> a من System.IO.Unsafe.يرجى ملاحظة أن هذه الوظيفة هي واحدة من أخطر الوظائف في هاسكل.لا تستخدمه، إذا لم تكن متأكدًا حقًا من العواقب.ولكن لغرضك، يبدو بخير.

نعم، سيكون هذا استخدامًا مشروعًا لـ unsafePerformIO.ولكن لا بأس إلا إذا كنت متأكدًا حقًا من عدم وجود تأثيرات مرئية.

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