سؤال

استمرار المسعى إلى الشعور بالوصول والأصدقاء. يرجى النظر في رمز (سخيف ولكن توضيح) أدناه:

v :: IO (Either String [String])
v = return $ Left "Error message"

doit :: IO (Either String ())
doit = (flip runContT return) $ callCC $ \k -> do
    x <- liftIO $ v
    x2 <- either (k . Left) return x
    when True $ k (Left "Error message 2")
    -- k (Left "Error message 3")
    return $ Right () -- success

هذا الرمز لا يترجم. ومع ذلك، إذا استبدل when مع مكالمة K المعلق أدناه، فإنه يجمع. ماذا يحدث هنا؟

بدلا من ذلك، إذا قمت بتعليق خط X2، فإنه يأتي أيضا. ؟؟؟

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

هل كانت مفيدة؟

المحلول

المشكلة هنا يجب أن تفعل مع أنواع when و either, ، وليس أي شيء خاص للمقاول:

when :: forall (m :: * -> *). (Monad m) => Bool -> m () -> m ()
either :: forall a c b. (a -> c) -> (b -> c) -> Either a b -> c

الحجة الثانية تحتاج إلى أن تكون من النوع m () لبعض موناد m. وبعد ال when وبالتالي يمكن تعديل خط الكود الخاص بك مثل ذلك:

when True $ k (Left "Error message 2") >> return ()

لجعل رمز تجميع التعليمات البرمجية. ربما هذا ليس ما تريد القيام به، لكنه يعطينا تلميحا فيما قد يكون خطأ: kتم استنتاج نوع "نوع غير قابل للتغيير when.

الآن ل either التوقيع: لاحظ أن الحججتين ل either يجب أن تكون وظائف تنتج نتائج من نفس النوع. نوع من return يتم تحديد هنا حسب نوع x, ، والتي بدورها ثابتة من قبل التوقيع الصريح v. وبعد وهكذا (k . Left) يجب أن يكون البت نفس النوع؛ هذا بدوره يعمل على إصلاح نوع k في (gg-styed)

k :: Either String () -> ContT (Either String ()) IO [String]

هذا غير متوافق مع whenتوقعات.

عندما تعلق x2 الخط، ومع ذلك، تتم إزالة تأثيره على طريقة عرض المدقق من النوع من التعليمات البرمجية، لذلك k لم يعد مجبرا على نوع غير مريح وهو مجاني في تحمل النوع

k :: Either [Char] () -> ContT (Either [Char] ()) IO ()

وهو ما يرام في whenكتاب. وبالتالي، فإن الرمز يجمع.

كملاحظة أخيرة، استخدمت منشأة نقاط التوقف في GHCI للحصول على الأنواع الدقيقة k تحت السيناريوهين - أنا في أي مكان بالقرب من الخبراء بما يكفي لكتابةها باليد وتكون بأي شكل من الأشكال من صحةها. :-) يستخدم :break ModuleName line-number column-number لمحاولة ذلك.

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