تحديد النطاق هاسكل في تعريفات الدالة المتداخلة باستخدام حيث
-
10-07-2019 - |
سؤال
ولدي مشكلة مع تحديد النطاق هاسكل في تعريفات where
. عندما يكون لدي f
الدالة التالية، حيث أريد لتمرير x
إلى وظيفة f1
المعرفة محليا دون explicitely استخدامه كمعلمة، أحصل على خطأ قائلا أن هذا النوع من x
غير متوافق مع واحد في إخراج f1
، على الرغم من أنه ينبغي أن يكون هو نفسه:
f :: Eq a => a -> [a] f x = f1 x where f1 :: Eq a => a -> [a] f1 y = [ x, y ]
والخطأ هو ما يلي:
Couldn't match expected type `a1' against inferred type `a' `a1' is a rigid type variable bound by the type signature for `f1' at test.hs:4:11 `a' is a rigid type variable bound by the type signature for `f' at test.hs:1:8 In the expression: x In the expression: [x, y] In the definition of `f1': f1 y = [x, y] Failed, modules loaded: none.
عند I لكن تمرير x
كمعلمة إضافية، كما فعلت في التعليمات البرمجية التالية مع g
وظيفة، فإنه يعمل بشكل جيد:
g :: Eq a => a -> [a] g x = g1 x x where g1 :: Eq a => a -> a -> [a] g1 x y = [ x, y ]
هل هناك طريقة لجعل a
نوع في f
متوافق مع نوع من a
(أو a1
) في f1
؟
المحلول
والمشكلة مع التعليمات البرمجية هي راقب محليا نوع F1 التوقيع. وهي تحدد أن F1 يمكن أن تتخذ أي نوع
وf1 :: Eq a => a -> [a]
وعلى الرغم من أن هذه هي وظيفة المحلية، وكنت قد عمم هذه الوظيفة لتكون قادرة على اتخاذ النوع الذي لن توجد داخل و مهما كان يتلقى هذه الوظيفة يجب أن يأتي من و، وبالتالي فإن توقيع نوع غير ضرورية.
ومجرد إزالة التوقيع نوع F1.
وتحرير: قراءة آخر ظهري لنفسي، فإنه من غير الواضح قليلا. وفي F1 هو نوع معلمات التي يمكن أن تأخذ أي شيء، ولكن الحجج التي تم تمريرها إلى أنه لا بد بالفعل في و. لذلك هذا وظيفة يمكن أن يحصل إلا ما تحصل وظيفة الأم، التوقيع نوع كنت يعطيها يكسر تلك القاعدة. نأمل هذا قليلا أكثر وضوحا.
نصائح أخرى
وديف هو حق أعلاه. وهناك طريقة أخرى للتفكير في الأمر هو أنه على الرغم من كل من التوقيعات النوع الخاص الرجوع إلى a
متغير، انها ليست في الواقع نفس نوع المتغير. في تدوين هاسكل، رئيس الوزراء، على حد سواء التوقيعات يمكن أن تكون مكتوبة بشكل أكثر وضوحا على النحو التالي:
وforall a . Eq a => a -> [a]
وهذا يعني أن ل<م> على حد سواء م> وظائف، فإنها يمكن أن نقبل حجة من أي نوع على الإطلاق (ضمن المعادلة). ومن الواضح أن هذا ليس هو الحال هنا. في معيار هاسكل 98، والخيار الوحيد هو التخلي عن توقيع نوع لf1
. لكن GHC (وغيرها؟) الدعم مفرداتيا متغيرات نوع راقب . لذلك يمكن أن تكتب
{-# LANGUAGE ScopedTypeVariables #-}
f :: forall a. Eq a => a -> [a]
f x = f1 x
where
f1 :: a -> [a]
f1 y = [ x, y ]
ووالتي من شأنها أن تعمل بشكل جيد.