التكرير (تقنية في البرمجة الوظيفية)

في الرياضيات وعلم الحاسوب، يُعدّ التكرير أو الكرّية أو التقييس ، تقنية لتحويل دالة تأخذ عدة وسائط إلى تسلسل من عائلات الدوال، تأخذ كل واحدة منها وسيطًا واحدًا فقط.

في المثال النموذجي، نبدأ بدالة  تأخذ وسيطين، أحدهما من  والآخر من ، وتنتج عناصر في  الشكل المحوَّر من هذه الدالة يعامل الوسيط الأول كمعامل، لتكوين عائلة من الدوال  وتُنظَّم هذه العائلة بحيث يوجد لكل عنصر  في  دالة واحدة فقط 

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

التحوير الكاري مرتبط بالتطبيق الجزئي، لكنه ليس الشيء نفسه. يمكن استخدام المثال أعلاه لتوضيح التطبيق الجزئي؛ وهو مشابه جدًا. التطبيق الجزئي هو الدالة  التي تأخذ الزوج  و كوسيطين معًا، وتُعيد  وباستخدام الترميز ذاته، تكون صيغة التطبيق الجزئي هي  ومكتوبة بهذه الطريقة، يمكن اعتبار دالة التطبيق مقابلة (adjoined) لدالة التحوير الكاري.

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

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

قُدّمت فكرة التحوير الكاري لأول مرة بواسطة جوتلوب فريجه, وطُوّرت لاحقًا بواسطة موسى شونفينكل،نُشر أولًا في 

نُشرت لاحقًا في  وطُوّر لاحقًا بواسطة هاسكل كاري.

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

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

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

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

 التاريخ 
الاسم "تكرير" أو "تقييس"  يعود إلى عالم المنطق هاسكل كاري، الذي استخدم هذا المفهوم على نطاق واسع، لكن  كان قد طرح الفكرة قبل كاري بست سنوات.
وقد تم اقتراح اسم بديل لهذا المفهوم وهو "شونفينكلية" (Schönfinkelisation).
في السياق الرياضي، يمكن تتبع هذا المبدأ إلى أعمال جوتلوب فريجه في عام 1893.

أما أصل مصطلح "currying" (التكرير) فليس واضحًا تمامًا. ديفيد تورنر يقول إن  هو من صاغ الكلمة في ملاحظاته الدراسية لعام 1967 بعنوان مفاهيم أساسية في لغات البرمجة،
لكن المصدر يقدّم المفهوم باعتباره "أداة من ابتكار شونفينكل"، ولا يستخدم مصطلح "currying" صراحة، رغم أن كاري يُذكر لاحقًا في سياق الدوال من الدرجة الأعلى.
أما جون س. رينولدز فقد عرّف مصطلح "currying" في ورقة بحثية عام 1972، لكنه لم يدّعِ أنه من ابتكره.

 التعريف 
يُفهم التقييس (Currying) بسهولة من خلال البدء بتعريف غير رسمي، يمكن بعد ذلك تكييفه ليناسب العديد من المجالات المختلفة. أولًا، يجب توضيح بعض الرموز. تشير الصيغة  إلى جميع الدوال من  إلى . وإذا كانت  دالة من هذا النوع، فإننا نكتب . وليكن  هو مجموعة الأزواج المرتبة من عناصر  و على التوالي، أي جداء ديكارتي لـ و. قد تكون  و مجموعات، أو أنواعًا (types)، أو أنواعًا أخرى من الكائنات، كما سيتم توضيحه لاحقًا.

إذا كانت لدينا دالة:

،

فإن عملية التقييس (currying) تُنشئ دالة جديدة:

.

أي أن  تأخذ معاملًا من النوع  وتُرجع دالة من النوع . وتُعرّف كما يلي:

حيث  من النوع  و من النوع . ويمكننا أيضًا كتابة:

أما إلغاء التقييس (Uncurrying) فهو التحويل العكسي، ويمكن فهمه بسهولة من خلال مرافقه الأيمن، وهو الدالة .

 نظرية المجموعات 
في نظرية المجموعات، يُستخدم الترميز  للدلالة على مجموعة الدوال من المجموعة  إلى المجموعة . والتقييس هو تناظر تقابلي طبيعي بين المجموعة  للدوال من  إلى ، والمجموعة  للدوال من  إلى مجموعة الدوال من  إلى . بالرموز:

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

في تصنيف المجموعات، يُطلق على كائن رياضي  اسم كائن أسي.

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

بينما تكون دالة uncurrying هي المعكوس لهذه الدالة. إذا أُعطيت المجموعة  من الدوال المستمرة من  إلى  طوبولوجيا منفتحة مضغوطة، وكان الفضاء  هاوسدورف موضعيًا مضغوط، فإن:

تكون تصاكل. ينطبق هذا أيضًا عندما تكون  و و فضاءات مولدة بطريقة مضغوطة، على الرغم من وجود حالات أكثر.

إحدى النتائج المفيدة هي أن الدالة تكون مستمرة إذا وفقط إذا كانت صورتها بطريقة curry مستمرة. نتيجة مهمة أخرى هي أن دالة "التطبيق"، والتي تُعرف عادةً باسم "التقييم" في هذا السياق، تكون مستمرة (لاحظ أن إيفال مفهوم مختلف تمامًا في علوم الحاسوب). أي أن:

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

 الطوبولوجيا الجبرية 
في طوبولوجيا جبرية، تُعد currying مثالًا على تطابق إيكمان–هيلتون، ولذلك تلعب دورًا مهمًا في سياقات متنوعة. على سبيل المثال، فضاء العقد هو المرافق لتعليق مختزل، ويُكتب عادة:

حيث  هي مجموعة تحاول بين الدوال ، و هو تعليق لـ"A"، و هو فضاء العقد لـ"A". من حيث الجوهر، يمكن اعتبار التعليق  كحاصل الضرب الكارتيزي لـ مع الفترة الواحدة، مع معاملته بعلاقة تكافؤ لتحويل الفترة إلى حلقة. الصورة بواسطة curry تربط الفضاء  إلى فضاء الدوال من الحلقات إلى ، أي من  إلى . وبالتالي، فإن  هو دالة مرافق تربط التعليقات بفضاءات العقد، وuncurrying هو النظير لها.

يمكن فهم الازدواجية بين مخروط التضمين وألياف التضمين (أي إدراج وإسقاط) كشكل من أشكال curry، مما يؤدي بدوره إلى الازدواجية بين متتالية منضبطة ومتتاليات بوبي العكسية.

في الجبر التماثلي، تُعرف العلاقة بين curry وuncurry باسم مرافقة الجداء التنسوري والدالة هوم، حيث تظهر ظاهرة مثيرة للاهتمام: قد لا تُرفع دالة هوم ودالة جداء موتر إلى متتالية منضبطة؛ ما يؤدي إلى تعريف دالة إكست ودالة تور.

 نظرية المجالات 
في نظرية الترتيب، أي نظرية شبكة لمجموعة مرتبة جزئيًا، تكون  دالة مستمرة عندما تُزود الشبكة بطوبولوجيا سكوت. لقد دُرست الدوال المستمرة وفق سكوت في البداية كجزء من محاولة لإيجاد دلالات لـتكامل لامدا (نظرًا لعدم كفاية نظرية المجموعات العادية لذلك). بشكل أعم، تُدرس هذه الدوال في نظرية المجالات، التي تشمل دراسة الدلالات التصويرية لخوارزميات الحاسوب. لاحظ أن طوبولوجيا سكوت تختلف كثيرًا عن العديد من الطوبولوجيات الشائعة في فئة الفضاءات الطوبولوجية؛ فهي عادةً ما تكون أدق، وليست فضاء رصين.

 حساب لامبدا 
في علم الحاسوب النظري، يوفر الكرّيان وسيلة لدراسة الدوال متعددة الوسائط ضمن نماذج نظرية بسيطة جدًا، مثل حساب لامبدا، حيث تأخذ الدوال وسيطًا واحدًا فقط. لنفترض وجود دالة  تأخذ وسيطين وتملك النوع ، مما يعني أن x يجب أن يكون من النوع ، وy من النوع ، بينما تُرجع الدالة نفسها قيمة من النوع . الشكل المُكرّى للدالة f يُعرّف على النحو التالي:

حيث  هو معامل التجريد في حساب لامبدا. وبما أن الكرّيان يأخذ كمدخل دوال من النوع ، فإن نوع الكرّيان ذاته يُستنتج كالتالي:

عادةً ما يُعتبر معامل  تجميعيًا إلى اليمين، لذلك يُكتب النوع  غالبًا بصيغة مختصرة . وبالمقابل، فإن تطبيق الدالة يُعتبر تجميعيًا إلى اليسار، لذا فإن التعبير  يعادل:

.

أي أن الأقواس ليست ضرورية لتوضيح ترتيب التطبيق.

يمكن استخدام الدوال المُكرّاة في أي لغة برمجة تدعم الإغلاق. ومع ذلك، غالبًا ما تُفضّل الدوال غير المُكرّاة لأسباب تتعلق بالكفاءة، إذ يمكن تجنب تكلفة التطبيق الجزئي وإنشاء الإغلاقات في معظم استدعاءات الدوال.

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

يُعبَّر عن هذا النهج النمطي في لغات برمجة مثل إم إل واللغات المتفرعة منها أو المتأثرة بها مثل كامل وهاسكل، وإف.

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

 المنطق 
بموجب تطابق كاري-هوارد، فإن وجود الكرّيان واللاكرّيان يعادل النظريّة المنطقية  (والمعروفة أيضًا باسم التصدير)، إذ إن النوع الضربي  يُقابل اقترانًا منطقيًا، ونوع الدالة يُقابل الاقتضاء.

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

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

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

حيث يُشير "هوم" إلى الدالة المراعية (الخارجية) التي تجمع جميع التشاكلات في الفئة، في حين يُمثل  الهوم الداخلي في الفئة المغلقة الأحادية. في فئة المجموعات، يتطابق الاثنان. وعندما يكون الجداء هو الجداء الديكارتي، يصبح الهوم الداخلي  هو الكائن الأسي .

قد يفشل الكرّيان في حالتين. الأولى، إذا لم تكن الفئة مغلقة، وبالتالي تفتقر إلى دالة هوم داخلية (ربما لوجود أكثر من خيار ممكن لهذه الدالة). والثانية، إذا لم تكن أحادية، أي أنها تفتقر إلى جداء (أي لا يوجد بها طريقة لتكوين أزواج من الكائنات). الفئات التي تمتلك كلاً من الجداءات والهومات الداخلية هي بالضبط الفئات المغلقة الأحادية.

يُعد إطار الفئات المغلقة الديكارتية كافيًا لمناقشة المنطق الكلاسيكي؛ أما الإطار العام للفئات المغلقة الأحادية فهو مناسب لـ الحوسبة الكمومية.

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

وعلى النقيض، فإن الجداء في الفئات الأحادية (مثل فضاء هيلبرت أو الفضاءات المتجهية في التحليل الدالي) هو جداء موتر. وتُعد المنطق الخطي هو اللغة الداخلية لهذه الفئات، وهي أحد أشكال المنطق الكمومي؛ ويُقابلها نظام الأنواع الخطي. تُستخدم هذه الفئات في توصيف التشابك الكمومي، كما تسمح — على نحو أوسع — بتعميم واسع لـ تطابق كاري-هوارد إلى ميكانيكا الكم، والمتعددات الحدية في الطوبولوجيا الجبرية، ونظرية الأوتار.

 التمايز عن التطبيق الجزئي للدوال 
غالبًا ما يُخلط بين الكرّية (Currying) والتطبيق الجزئي للدوال (Partial Function Application).
من الفروقات الجوهرية بينهما أن استدعاء دالة مطبَّقة جزئيًا يُرجع النتيجة مباشرة، وليس دالة أخرى في سلسلة الكرّية؛ ويمكن توضيح هذا الفرق بسهولة أكبر عند التعامل مع دوال ذات عدد كبير من الوسيطات (أي الأريتي > 2).

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

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

من حيث الفهم الحدسي، يمكن القول إن التطبيق الجزئي يعني: "إذا ثبّتت أول وسيط في دالة، ستحصل على دالة تقبل باقي الوسائط". على سبيل المثال، إذا كانت الدالة div تمثل عملية القسمة x ÷ y، فإن تثبيت x عند 1 (أي div 1) ينتج دالة مساوية للدالة inv التي تُرجع مقلوب الوسيط، أي: inv(y) = 1 ÷ y.

الدافع العملي للتطبيق الجزئي هو أن الدوال الناتجة عن تزويد بعض، وليس كل، الوسائط تكون غالبًا مفيدة؛ على سبيل المثال، العديد من اللغات توفر دوال مثل plus\_one، والتي يمكن إنشاؤها بسهولة عن طريق تثبيت الوسيط الأول لدالة الجمع عند 1.

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

وبالتالي، فإن التطبيق الجزئي ما هو إلا دالة كرّية تم تقييمها عند نقطة معينة. وبالمثل، فإن أي دالة كرّية عند نقطة معينة تُعد تطبيقًا جزئيًا.
ولمزيد من الإثبات، يمكن القول إنه إذا كانت لدينا دالة ، فيمكننا تعريف دالة  بحيث ؛ مما يدل على أن أي تطبيق جزئي يمكن اختزاله إلى عملية كرّية واحدة.

من هنا، يمكن تعريف التطبيق الجزئي على أنه الناتج الفعلي لتطبيق واحد لعملية الكرّية على ترتيب معين لوسائط دالة معينة.

 انظر أيضًا 
 تثمين كسول

 المراجع 

 وصلات خارجية 

تصنيف:برمجة وظيفية
تصنيف:حسابات اللامدا