تحديد النطاق هاسكل في تعريفات الدالة المتداخلة باستخدام حيث

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

سؤال

ولدي مشكلة مع تحديد النطاق هاسكل في تعريفات 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 ]

ووالتي من شأنها أن تعمل بشكل جيد.

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