كاري (لغة برمجة)

كاري هي لغة برمجة تصريحية ، وهي تطبيق لنموذج البرمجة الوظيفية المنطقية ، [ 2 ] [ 3 ] [ 4 ] وتعتمد على لغة هاسكل . وهي تدمج عناصر البرمجة الوظيفية والمنطقية، [ 5 ] بما في ذلك تكامل البرمجة المقيدة .

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

أسس البرمجة المنطقية الوظيفية

المفاهيم الأساسية

البرنامج الوظيفي هو مجموعة من الدوال المُعرَّفة بمعادلات أو قواعد. تتألف العملية الحسابية الوظيفية من استبدال التعبيرات الفرعية بتعبيرات فرعية مساوية لها (فيما يتعلق بتعريفات الدوال) حتى يتعذر إجراء المزيد من الاستبدالات (أو الاختزالات) والحصول على قيمة أو صيغة طبيعية. على سبيل المثال، لنفترض الدالة double المُعرَّفة بـ

x المزدوج = x+x

يُستبدل التعبير " double 1 " بـ 1+1 . ويمكن استبدال الأخير بـ 2 إذا فسرنا عامل الجمع " + " على أنه مُعرَّف بمجموعة لا نهائية من المعادلات، مثل 1+1 = 2 ، 1+2 = 3 ، وهكذا. وبطريقة مماثلة، يمكن تقييم التعبيرات المتداخلة (حيث تُوضع التعبيرات الفرعية المراد استبدالها بين علامتي اقتباس):

'double (1+2)' → '(1+2)'+(1+2) → 3+'(1+2)' → '3+3' → 6

يوجد أيضًا ترتيب آخر للتقييم إذا قمنا باستبدال وسائط المعاملات من اليمين إلى اليسار:

'double (1+2)' → (1+2)+'(1+2)' → '(1+2)'+3 → '3+3' → 6

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

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

البيانات المنطقية = صحيح | خطأ

يمكن تعريف الدوال على القيم المنطقية عن طريق مطابقة الأنماط، أي من خلال توفير عدة معادلات لقيم وسيطات مختلفة:

ليس صحيحًا = خطأ، ليس خطأً = صحيح

يظل مبدأ استبدال كلمة "يساوي" بكلمة "يساوي" ساريًا بشرط أن تكون الوسائط الفعلية بالشكل المطلوب، على سبيل المثال:

ليس '(ليس خطأ)' → 'ليس صحيحًا' → خطأ

يمكن الحصول على هياكل بيانات أكثر تعقيدًا باستخدام أنواع البيانات المتكررة . على سبيل المثال، قائمة العناصر، حيث يكون نوع العناصر عشوائيًا (يُشار إليه بمتغير النوع a )، هي إما قائمة فارغة " [] " أو قائمة غير فارغة " x:xs " تتكون من عنصر أول x وقائمة xs :

قائمة البيانات أ = [] | أ : قائمة أ

يُكتب النوع " List a " عادةً على الصورة [ a ] ، بينما تُكتب القوائم المنتهية x1 : x2 : : xn : [] على الصورة [ x1 , x2 , , xn ] . يمكننا تعريف العمليات على الأنواع التكرارية باستخدام التعريفات الاستقرائية، حيث يدعم مطابقة الأنماط الفصل المريح بين الحالات المختلفة. على سبيل المثال، يمكن تعريف عملية الربط " ++ " على القوائم متعددة الأشكال كما يلي (يُحدد إعلان النوع الاختياري في السطر الأول أن " ++ " تأخذ قائمتين كمدخلات وتُنتج قائمة مخرجات، حيث تكون جميع عناصر القائمة من نفس النوع غير المحدد):

( ++ ) :: [ a ] -> [ a ] -> [ a ] [] ++ ys = ys ( x : xs ) ++ ys = x : xs ++ ys

إلى جانب استخدامها في مهام البرمجة المختلفة، تُعدّ عملية " ++ " مفيدةً أيضًا لتحديد سلوك الدوال الأخرى على القوائم. على سبيل المثال، يمكن تحديد سلوك الدالة last التي تُعيد العنصر الأخير من قائمة ما على النحو التالي: لكل قائمة xs وعناصر last xs = e إذا كان ∃ ys : ys ++[ e ] = xs.

استنادًا إلى هذه المواصفات، يمكن تعريف دالة تُحققها باستخدام خصائص البرمجة المنطقية. وكما هو الحال في لغات المنطق، تُتيح لغات المنطق الوظيفي البحث عن حلول للمتغيرات المُكمّمة وجوديًا. وعلى عكس لغات المنطق البحتة، تدعم هذه اللغات حل المعادلات على التعبيرات الوظيفية المتداخلة، بحيث تُحل معادلة مثل ys ++[ e ] = [1,2,3] بتعيين قيمة ys إلى القائمة [1,2] وقيمة e إلى 3. في لغة كاري، يمكن تعريف العملية الأخيرة كما يلي:

last xs | ys ++ [ e ] =:= xs = e where ys , e free

هنا، يُستخدم الرمز " =:= " للقيود المعادلة لتوفير تمييز نحوي عن المعادلات المُعرِّفة. وبالمثل، تُصرَّح المتغيرات الإضافية (أي المتغيرات غير الموجودة في الجانب الأيسر من المعادلة المُعرِّفة) صراحةً باستخدام " where … free " لإتاحة بعض الفرص لاكتشاف الأخطاء الناتجة عن الأخطاء المطبعية. تُطبَّق المعادلة الشرطية من الشكل L | C = R للاختزال إذا تم حل شرطها C. على عكس اللغات الوظيفية البحتة حيث تُقيَّم الشروط فقط إلى قيمة منطقية، تدعم لغات المنطق الوظيفي حل الشروط عن طريق تخمين قيم المجاهيل في الشرط. يُستخدم التضييق، كما هو موضح في القسم التالي، لحل هذا النوع من الشروط.

تضييق

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

يُعدّ التضييق مفيدًا لأنه يسمح بالتعامل مع الدالة كعلاقة: إذ يمكن حساب قيمتها "في كلا الاتجاهين". وتوضح أمثلة كاري في القسم السابق هذا الأمر.

كما ذُكر في القسم السابق، يُمكن اعتبار التضييق بمثابة اختزال في مخطط مصطلحات البرنامج، وغالبًا ما توجد طرق ( استراتيجيات ) عديدة لاختزال مخطط مصطلحات مُعين. وقد أثبت أنطوى وآخرون [ 6 ] في تسعينيات القرن الماضي أن استراتيجية تضييق مُحددة، وهي التضييق المطلوب ، تُعدّ مثالية بمعنى إجراء عدد من عمليات الاختزال للوصول إلى "صيغة طبيعية" تُطابق حلاً أدنى بين الاستراتيجيات السليمة والكاملة. ويُقابل التضييق المطلوب استراتيجية كسولة، على عكس استراتيجية حل SLD في لغة برولوج .

الأنماط الوظيفية

تُعبّر القاعدة الأخيرة الموضحة أعلاه عن حقيقة أن الوسيط الفعلي يجب أن يتطابق مع نتيجة تضييق التعبير ys++[e] . ويمكن لـ Curry التعبير عن هذه الخاصية أيضًا بالطريقة الأكثر إيجازًا التالية:

last ( ys ++ [ e ]) = e

لا تسمح لغة هاسكل بمثل هذا التصريح لأن النمط الموجود على الجانب الأيسر يحتوي على دالة مُعرَّفة ( ++ ). يُطلق على هذا النمط أيضًا اسم النمط الوظيفي . [ 7 ] تُفعَّل الأنماط الوظيفية بفضل الميزات الوظيفية والمنطقية المُدمجة في لغة كاري، وتدعم تعريفات مُوجزة للمهام التي تتطلب مطابقة أنماط عميقة في هياكل البيانات الهرمية.

اللا حتمية

بما أن لغة كاري قادرة على حل المعادلات التي تحتوي على استدعاءات دوال بقيم مجهولة، فإن آلية تنفيذها تعتمد على حسابات غير حتمية، على غرار البرمجة المنطقية. تدعم هذه الآلية أيضًا تعريف العمليات غير الحتمية ، أي العمليات التي تُنتج أكثر من نتيجة واحدة لمدخل مُعطى. يُعدّ عامل الاختيار (?) ، وهو عامل مُعرّف مسبقًا، النموذج الأولي للعمليات غير الحتمية ، حيث يُعيد أحد وسيطيه. يُعرّف هذا العامل وفقًا للقواعد التالية:

س ؟ ص = س س ؟ ص = ص

وبالتالي، فإن تقييم التعبير 0 ? 1 يُرجع 0 وكذلك 1. إن الحساب باستخدام العمليات غير الحتمية والحساب باستخدام المتغيرات الحرة عن طريق التضييق لهما نفس القدرة التعبيرية. [ 8 ] 

تُظهر القواعد التي تُعرّف علامة الاستفهام سمةً مهمةً في خوارزمية كاري: حيث تُجرَّب جميع القواعد لتقييم عمليةٍ ما. وبالتالي، يمكن تعريفها بواسطة

أدخل x ys = x : ys أدخل x ( y : ys ) = y : أدخل x ys

عملية لإدراج عنصر في قائمة في موضع غير محدد بحيث تكون العملية مُعرَّفة بواسطة

perm [] = [ ] perm ( x : xs ) = insertx ( perm xs )

تُعيد أي تبديل لقائمة إدخال معينة.

الاستراتيجيات

نظرًا لغياب الآثار الجانبية، يمكن تنفيذ برنامج منطقي وظيفي باستخدام استراتيجيات مختلفة. لتقييم التعبيرات، تستخدم لغة كاري صيغة معدلة من استراتيجية التضييق المطلوبة ، والتي تجمع بين التقييم الكسول واستراتيجيات البحث غير الحتمية. على عكس لغة برولوج، التي تستخدم التراجع للبحث عن الحلول، لا تُحدد لغة كاري استراتيجية بحث معينة. لذا، توجد تطبيقات للغة كاري، مثل KiCS2 ، حيث يمكن للمستخدم بسهولة اختيار استراتيجية بحث، مثل البحث العميق أولًا (التراجع)، أو البحث العرضي أولًا ، أو التعمق التكراري، أو البحث المتوازي.

أدوات التنفيذ والبرمجة

تتوفر تطبيقات متنوعة لـ Curry. ومن أبرزها نظام بورتلاند آخن كيل كاري PAKCS الذي يقوم بتجميع برامج Curry إلى Prolog ، ونظام كيل كاري KiCS2 الذي يقوم بتجميع برامج Curry إلى Haskell ، ومترجم مونستر كاري MCC ، و Curry2Go الذي يقوم بتجميع برامج Curry إلى برامج Go ويدعم البحث المتوازي العادل عن طريق ربط التقييمات غير الحتمية بعمليات خفيفة الوزن (goroutines).

لدعم البرمجة بلغة Curry، هناك مجموعة من حزم برامج Curry ، ومحرك بحث Curry API ، وخادم لغة Curry يوفر دعم IDE ، على سبيل المثال، في Visual Studio Code ، بالإضافة إلى أدوات توثيق وتحليل البرامج المختلفة.

مناقشة وقراءات إضافية

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

يحتوي الكتاب المدرسي [ 10 ] حول مبادئ وممارسة لغات البرمجة على فصل عن البرمجة بلغة كاري.

مراجع

  1. "PAKCS الإصدار 3.8.0 (07/04/25)" .
  2. هانوس، مايكل (محرر). "كاري: لغة منطقية وظيفية متكاملة حقًا" .
  3. سيرجيو، أنتوي؛ هانوس، مايكل (2010). "برمجة المنطق الوظيفي". اتصالات رابطة مكائن ​​الحوسبة . 53 (4). رابطة مكائن ​​الحوسبة: 74-85 . doi : 10.1145/1721654.1721675 . S2CID 14578759 . 
  4. هانوس، مايكل (2013). "برمجة المنطق الوظيفي: من النظرية إلى تطبيق كاري". منطق البرمجة - مقالات في ذكرى هارالد غانزينغر . سلسلة محاضرات في علوم الحاسوب. المجلد 7797. الصفحات 123-168 . doi : 10.1007/978-3-642-37651-1_6 . ISBN   978-3-642-37650-4.
  5. "لغة برمجة تجريبية من نوع كاري" . MVPS.net . تم الاطلاع عليه بتاريخ 2 سبتمبر 2021 .
  6. سيرجيو، أنتوي؛ إحاذيد، رشيد؛ هانوس، مايكل (2000). "استراتيجية تضييق ضرورية". مجلة ACM . 47 (4). ACM: 776–822 . doi : 10.1145/347476.347484 . hdl : 11858/00-001M-0000-0014-B494-9 . ISSN 0004-5411 . S2CID 47275506 .  
  7. أنطوى، سيرجيو؛ هانوس، مايكل (2006). "البرمجة التصريحية باستخدام أنماط الدوال". توليف البرامج وتحويلها القائم على المنطق . سلسلة محاضرات في علوم الحاسوب. المجلد 3901. الصفحات 6-22 . doi : 10.1007/11680093_2 . ISBN   978-3-540-32654-0.
  8. أنطوى، سيرجيو؛ هانوس، مايكل (2006). "القواعد المتداخلة ومتغيرات المنطق في برامج المنطق الوظيفي". برمجة المنطق . سلسلة محاضرات في علوم الحاسوب. المجلد 4079. الصفحات 87-101 . doi : 10.1007/11799573_9 . ISBN   978-3-540-36635-5.
  9. روبنسون، جون آلان (2000). "المنطق الحسابي: ذكريات الماضي وتحديات المستقبل". المؤتمر الدولي الأول حول المنطق الحسابي (CL 2000) . سلسلة محاضرات في علوم الحاسوب. المجلد 1861. الصفحات 1-24 . doi : 10.1007/3-540-44957-4_1 . ISBN   978-3-540-67797-0.
  10. لودن، كينيث سي؛ لامبرت، كينيث أ. (2012). لغات البرمجة - المبادئ والتطبيق . سينجايج ليرنينج. ISBN 978-1-111-57763-6.