ZuriHac: ممارسة البرمجة الوظيفية

في يونيو من هذا العام ، تم تنظيم حدث يسمى ZuriHac للمرة العاشرة في بلدة Rapperswil السويسرية الصغيرة. هذه المرة تجمع أكثر من خمسمائة من عشاق هاسكل من المبتدئين إلى الآباء المؤسسين للغة. على الرغم من أن المنظمين يصفون هذا الحدث بأنه "hackathon" ، إلا أنه ليس مؤتمرا أو hackathon بالمعنى الكلاسيكي. شكله يختلف عن البرمجة التقليدية. لقد تعلمنا عن ZuriHac بمصادفة محظوظة ، وشاركنا فيها ، والآن نعتبر أنه من واجبنا أن نتحدث عن اكتشاف غير عادي!




عنا


تم إعداد هذا المقال من قبل اثنين من طلاب السنة الثالثة في برنامج الرياضيات التطبيقية وعلوم الحاسب في المدرسة العليا للاقتصاد - سانت بطرسبرغ: فاسيلي ألفيروف وإليزافيتا فاسيلينكو. بدأت شغف البرمجة الوظيفية لكلينا مع سلسلة من المحاضرات التي أدلى بها D.N. Moskvin في السنة الثانية من الجامعة. يشارك فاسيلي حاليًا في برنامج Google Summer of Code ، والذي يشارك في تنفيذ الرسوم البيانية الجبرية بلغة هاسكل تحت إشراف فريق مشروع Alga . طبقت إليزابيث المهارات المكتسبة للبرمجة الوظيفية في عمل المقرر المكرس لتنفيذ خوارزمية مناهضة التوحيد مع الاستخدام اللاحق في نظرية النوع.

تنسيق الحدث


الجمهور المستهدف هو أصحاب المشاريع مفتوحة المصدر والمبرمجين الذين يرغبون في المشاركة في تنميتهم ، والباحثين عن البرمجة الوظيفية والأشخاص الذين هم ببساطة متحمسون لهاسكل. في هذا العام ، ضم موقع HSR Hochschule für Technik Rapperswil University مطورين من أكثر من خمسين مشروعًا مفتوحًا من مصادر Haskell من جميع أنحاء العالم للحديث عن منتجاتهم واهتمام الأشخاص الجدد بتطورهم.



صور من التغريد ZuriHac

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

ليس لدينا مشاريعنا المفتوحة حتى الآن ، لكننا نريد حقًا المساهمة في المشروعات القائمة ، لذلك قمنا بالتسجيل كمشاركين منتظمين. لمدة ثلاثة أيام عملنا مع اثنين من فرق التطوير. اتضح أن الدراسة المشتركة للرمز والاتصال المباشر تجعل تفاعل مؤلفي المشروع والمساهمين مثمرًا للغاية - في ZuriHac تمكنا من اكتشاف مجالات جديدة لنا وتمكنا من مساعدة فريقين مختلفين تمامًا من خلال إغلاق المهمة في كل من المشاريع.

بالإضافة إلى الممارسة القيمة ، تم تقديم العديد من المحاضرات ودروس الماجستير في ZuriHac. نتذكر بشكل خاص محاضرتين. في البداية ، تحدث أندريه موخوف من جامعة نيوكاسل عن الدوافع التطبيقية الانتقائية - فئة من النوع الذي يجب أن يصبح وسيطًا بين الدوافع التطبيقية والموناديات. في محاضرة أخرى ، تحدث أحد مؤسسي هاسكل ، سايمون بيتون جونز ، عن كيفية عمل الاستدلال النوعي في برنامج التحويل البرمجي GHC.



محاضرة لسيمون بيتون جونز. صور من التغريد ZuriHac

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

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

والآن سنتحدث عن المشاريع التي قمنا بتطويرها.

Pandoc


Pandoc عبارة عن محول عالمي للمستندات النصية ، في الواقع - من أي تنسيق إلى أي. على سبيل المثال ، من docx إلى pdf ، أو من Markdown إلى MediaWiki. مؤلفها ، جون ماكفارلين ، أستاذ الفلسفة في جامعة كاليفورنيا ، بيركلي. بشكل عام ، Pandoc مشهورة جدًا ، وقد فوجئ بعض أصدقائنا عندما علموا أن Pandoc كتب بلغة Haskell.



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

بالطبع ، لا يقوم Pandoc بتنفيذ التحويل المباشر لكل زوج من التنسيقات. لدعم هذه المجموعة الواسعة من التحويلات ، يتم استخدام حل معماري قياسي: أولاً ، يتم ترجمة المستند بأكمله إلى تمثيل وسيط داخلي خاص ، ثم يتم إنشاء مستند بتنسيق مختلف من هذا التمثيل الداخلي. يقوم المطورون باستدعاء التمثيل الداخلي "AST" ، والذي يرمز لشجرة Syntax Tree أو شجرة بناء الجملة abstract . يمكنك إلقاء نظرة على التمثيل الوسيط بكل بساطة: لذلك عليك فقط تعيين "الأصلي" كتنسيق الإخراج

$ cat example.html <h1>Hello, World!</h1> $ pandoc -f html -t native example.html [Header 1 ("hello-world",[],[]) [Str "Hello,",Space,Str "World!"]] 

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

لذلك ، هنا يمكنك أن ترى أن التمثيل الداخلي هو بنية متكررة ، في كل عقدة داخلية توجد قائمة بها. على سبيل المثال ، في المستوى الأعلى ، توجد قائمة بعنصر واحد - رأس المستوى الأول ذو السمات "hello-world" ، [] ، []. داخل هذا الرأس توجد قائمة بسلسلة "Hello" ومسافة وسلسلة "World!".

كما ترون ، فإن التمثيل الداخلي لا يختلف كثيرًا عن HTML. إنها شجرة ، حيث تقوم كل عقدة داخلية بالإبلاغ عن بعض المعلومات حول تنسيق أحفادها ، وتحتوي الأوراق على المحتويات الفعلية للمستند.

إذا انتقلت إلى مستوى تطبيق معين ، فسيتم تعريف نوع البيانات للمستند بأكمله على النحو التالي:

 data Pandoc = Pandoc Meta [Block] 

هنا ، تعتبر Block هي القمم الداخلية المذكورة أعلاه بالتحديد ، و Meta هي معلومات التعريف حول المستند ، مثل العنوان وتاريخ الإنشاء والمؤلفين - وهذا يختلف عن التنسيقات المختلفة ، ويحاول Pandoc حفظ هذه المعلومات كلما كان ذلك ممكنًا عند النقل من التنسيق إلى التنسيق.

جميع المنشئات من نوع Block تقريبًا - على سبيل المثال ، Header أو Para (الفقرة) - لها سمات وقائمة من الرؤوس ذات المستوى الأدنى - مضمّنة ، وكقاعدة عامة ، كوسائط. على سبيل المثال ، يعتبر Space أو Str مصممًا لنوع Inline ، ويتم أيضًا تحويل علامة HTML إلى Inline خاص به. لا نرى أي سبب لإعطاء تعريف كامل لهذه الأنواع ، ومع ذلك ، نلاحظ أنه يمكن رؤيته هنا .

ومن المثير للاهتمام ، نوع Pandoc هو monoid. هذا يعني أن هناك نوعًا من المستندات الفارغة ، ويمكن تكديس هذه المستندات فيما بينها. هذا مناسب للاستخدام عند كتابة القراء - يمكنك تقسيم الوثيقة إلى أجزاء ذات منطق تعسفي ، وتحليل كل منها على حدة ، ثم تجميع كل شيء في وثيقة واحدة. في هذه الحالة ، سيتم جمع معلومات التعريف من جميع أجزاء المستند في وقت واحد.

عند التحويل ، على سبيل المثال ، من LaTeX إلى HTML ، تقوم وحدة نمطية خاصة تسمى LaTeXReader أولاً بتحويل مستند الإدخال إلى AST ، ثم تقوم وحدة نمطية أخرى تسمى HTMLWriter بتحويل AST إلى HTML. بفضل هذه البنية ، ليس من الضروري كتابة عدد من التحويلات التربيعية - يكفي أن تكتب Reader و Writer لكل تنسيق جديد ، وسيتم دعم جميع أزواج التحويلات الممكنة تلقائيًا.

من الواضح أن هذه البنية لها أيضًا عيوبها التي توقعها الخبراء في مجال هندسة البرمجيات منذ فترة طويلة. الأهم هو تكلفة إجراء تغييرات على شجرة بناء الجملة. إذا كان التغيير خطيرًا بدرجة كافية ، فسيتعين عليك تغيير الشفرة في جميع القراء والكتاب. على سبيل المثال ، يتمثل أحد التحديات التي تواجه مطوري Pandoc في دعم تنسيقات جدول معقدة. يمكن الآن لـ Pandoc فقط في أبسط الجداول ، مع العنوان والأعمدة والقيمة في كل خلية. لنفترض أنه سيتم تجاهل سمة colspan في HTML. أحد أسباب هذا السلوك هو عدم وجود نظام تمثيل جدول واحد في جميع أو على الأقل العديد من التنسيقات - وبالتالي ، فمن غير الواضح في ما شكل الجداول يجب أن يتم تخزينها في التمثيل الداخلي. ولكن حتى بعد اختيار طريقة عرض محددة ، سيكون من الضروري تغيير كل القراء والكتاب الذين يدعمون العمل مع الجداول.

تم اختيار هاسكل ليس فقط من حب كبير للمؤلفين للبرمجة الوظيفية. تشتهر هاسكل بقدراتها القوية في معالجة النصوص. ومن الأمثلة على ذلك مكتبة parsec - وهي مكتبة تستخدم مفاهيم البرمجة الوظيفية بنشاط - المونويدات ، والموناديات ، والمجانين التطبيقية والبديلة - لكتابة المحللون التعسفيين. يمكن رؤية القوة الكاملة لـ Parsec في مثال HaskellWiki ، الذي يوزع المحلل اللغوي الكامل للغة برمجة بسيطة ضرورية. بالطبع ، يستخدم بارسيك بنشاط في Pandoc.

باختصار ، تُستخدم الأحاديات للتحليل المتسلسل عندما يأتي الأول أولاً ثم الآخر. على سبيل المثال ، في هذا المثال:

 whileParser :: Parser Stmt whileParser = whiteSpace >> statement 

تحتاج أولاً إلى التفكير في مساحة ، ثم العبارة - التي تحتوي أيضًا على نوع Parser Stmt.

تستخدم الدالات البديلة لاستعادة إذا فشل التحليل. على سبيل المثال

 statement :: Parser Stmt statement = parens statement <|> sequenceOfStmt 

يعني أنك تحتاج إلى إما محاولة قراءة العبارة بين قوسين ، أو محاولة قراءة عدة عبارات بالتسلسل.

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

 const <$> tok <*> tok 

سوف تقرأ رمزين على التوالي وتعود إلى أولهما.

لدى Haskell عوامل تشغيل رمزية جميلة لكل هذه الفئات ، مما يجعل برامج قراءة الكتب تبدو وكأنها فن ASCII. فقط معجب بهذا الرمز الرائع.

كانت مهامنا متعلقة بـ LaTeXReader. كانت مهمة فاسيلي هي دعم الأمرين \ mbox و \ hbox ، وهي مفيدة عند كتابة الحزم في LaTeX. كانت إليزابيث مسؤولة عن دعم فريق \ epigraph ، الذي يسمح بتنفيذ النصوص في مستندات LaTeX.

Hatrace


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

Hatrace هي مكتبة توفر واجهة ل ptrace في Haskell. والحقيقة هي أن ptrace نفسها متطورة للغاية ومن الصعب جدا استخدامها مباشرة ، وخاصة من اللغات الوظيفية.

يعمل Hatrace عند بدء التشغيل مثل strace ويتقبل الحجج المماثلة. الاختلاف بينه وبين الشرائط هو أنها مكتبة توفر واجهة أكثر بساطة من مجرد ptrace.

لقد حصل Hatrace بالفعل على خطأ واحد غير سار في برنامج التحويل البرمجي Haskell GHC - عندما يتم قتله في الوقت الخطأ ، فإنه يولد ملفات كائنات غير صحيحة ولا يعيد ترجمتها عند إعادة التشغيل. مكّنت البرمجة النصية على مكالمات النظام من إعادة إنتاج الخطأ بشكل مضمون في مرة واحدة ، عندما أعادت عمليات القتل العشوائي الخطأ في غضون ساعتين تقريبًا.

أضفنا واجهات استدعاء النظام إلى المكتبة - أضافت Elizabeth brk ، وأضاف فاسيلي mmap. وفقًا لنتائج عملنا ، يمكننا استخدام وسيطات مكالمات النظام هذه بسهولة ودقة أكبر عند استخدام المكتبة.

Source: https://habr.com/ru/post/ar460537/


All Articles