اكتب خطأ أثناء محاولة تنفيذ وظيفة (>> =) من أجل إنشاء محول موناد مخصص
-
27-09-2019 - |
سؤال
أحاول إنشاء محول موناد لمشروع مستقبلي ، لكن لسوء الحظ ، لا يعمل تنفيذ وظيفة monad typeclasse (>> =).
بادئ ذي بدء ، إليك تطبيق Monad الأساسي:
newtype Runtime a = R {
unR :: State EInfo a
} deriving (Monad)
هنا ، يتم تنفيذ monad typeclasse تلقائيًا بواسطة GHC (باستخدام GeneralizedNewtypeDeriving
لغة البراغما). يتم تعريف محول Monad على النحو التالي:
newtype RuntimeT m a = RuntimeT {
runRuntimeT :: m (Runtime a)
}
تأتي المشكلة من الطريقة التي أقوم بتأسيس وظيفة (>> =) من monad typeclasse:
instance (Monad m) => Monad (RuntimeT m) where
return a = RuntimeT $ (return . return) a
x >>= f = runRuntimeT x >>= id >>= f
الطريقة التي أراها الأولى >>=
يركض في الأساس m
موناد. هكذا، runRuntimeT x >>=
إرجاع قيمة النوع Runtime a
(حقا ؟). ثم ، الرمز التالي ، id >>=
, ، يجب إرجاع قيمة النوع a
. هذه القيمة هي تم نقلها إلى وظيفة F من النوع f :: (Monad m) => a -> RuntimeT m b
.
وهنا تأتي مشكلة النوع: f
لا يتطابق نوع الوظيفة مع النوع المطلوب بواسطة دالة (>> =). جو هل يمكنني جعل هذا متماسك؟ أستطيع أن أرى لماذا هذا لا يعمل ، لكن لا يمكنني تحويله إلى شيء وظيفة.
تحرير: رسالة الخطأ:
Core.hs:34:4:
Occurs check: cannot construct the infinite type: m = RuntimeT m
When generalising the type(s) for `>>='
In the instance declaration for `Monad (RuntimeT m)'
Failed, modules loaded: none.
شكرًا لك على المساعدة ، ولا تتردد في تصحيح أي عيوب في رسالتي ،
تشارلي ب.
المحلول
لمتابعة ما قاله ريد بارتون عن StateT
- إليك كيف ستحددها RuntimeT
استخدام StateT
. ال Runtime
يمكن بعد ذلك تحديد موناد بشكل تافهة باستخدام موناد الهوية.
newtype RuntimeT m a = R {
unR :: StateT EInfo m a
}
type Runtime = RuntimeT Identity
instance Monad m => Monad (RuntimeT m) where
return = R . return
(R m) >>= f = R (m >>= unR . f)
نصائح أخرى
المعتاد StateT s m
موناد يرسل a
إلى s -> m (a, s)
لكنك تعمل مع m (s -> (a, s))
في حين أن. لا أعتقد أن هذا الأخير يشكل مونادًا للجنرال s
. هل أنت متأكد من أنك لا تريد استخدامها فقط StateT
?
هذا لماذا لا أعتقد a
→ m (s -> (a, s))
موناد: الكتابة >>=
أحتاج إلى وظيفة تأخذ حجج الأنواع
m (s -> (a, s))
a -> m (s -> (b, s))
وإرجاع قيمة النوع
m (s -> (b, s))
"الآثار" (أي fmap (const ())
) من النتيجة يجب أن تكون تلك الموجودة في الحجة الأولى ، حيث ليس لدينا طريقة للحصول على a
لتمرير الحجة الثانية. حيث m
يظهر فقط في الخارج من نوع النتيجة ، بعد ذلك لا يمكننا استخدام الوسيطة الثانية لأي شيء على الإطلاق - لن تكون هناك طريقة للتخلص من m
يقدم.