لماذا لا يكتب هذا الرمز الموند التحقق؟
سؤال
instance Monad (Either a) where
return = Left
fail = Right
Left x >>= f = f x
Right x >>= _ = Right x
تسبب هذا الرمز في 'Baby.HS' في خطأ التجميع الرهيب:
Prelude> :l baby
[1 of 1] Compiling Main ( baby.hs, interpreted )
baby.hs:2:18:
Couldn't match expected type `a1' against inferred type `a'
`a1' is a rigid type variable bound by
the type signature for `return' at <no location info>
`a' is a rigid type variable bound by
the instance declaration at baby.hs:1:23
In the expression: Left
In the definition of `return': return = Left
In the instance declaration for `Monad (Either a)'
baby.hs:3:16:
Couldn't match expected type `[Char]' against inferred type `a1'
`a1' is a rigid type variable bound by
the type signature for `fail' at <no location info>
Expected type: String
Inferred type: a1
In the expression: Right
In the definition of `fail': fail = Right
baby.hs:4:26:
Couldn't match expected type `a1' against inferred type `a'
`a1' is a rigid type variable bound by
the type signature for `>>=' at <no location info>
`a' is a rigid type variable bound by
the instance declaration at baby.hs:1:23
In the first argument of `f', namely `x'
In the expression: f x
In the definition of `>>=': Left x >>= f = f x
baby.hs:5:31:
Couldn't match expected type `b' against inferred type `a'
`b' is a rigid type variable bound by
the type signature for `>>=' at <no location info>
`a' is a rigid type variable bound by
the instance declaration at baby.hs:1:23
In the first argument of `Right', namely `x'
In the expression: Right x
In the definition of `>>=': Right x >>= _ = Right x
Failed, modules loaded: none.
لماذا يحدث هذا؟ وكيف يمكنني عمل هذا الرمز؟ شكرا على أي مساعدة ~
أنا أرى. وقمت بتعديل الكود لرؤيته يجمع:
instance Monad (Either a) where
return = Right
Left a >>= f = Left a
Right x >>= f = f x
يجمع بنجاح! لكن ... لمزيد من السؤال:
instance Monad (Either a)
يجعل "إما" موناد وحصلت على "العودة = يمين" ... كيف يمكنني الحصول على "العودة = اليسار"؟ لقد جربت هذا ولكن فشلت:
instance Monad (`Either` a) where
return = Left
Right a >>= f = Right a
Left x >>= f = f x
أو: مثيل monad ( x -> إما xa)
لا يجمع على الإطلاق!
المحلول
- يجب أن يكون للعودة نوع
forall b. b -> Either a b
, ومع ذلك اليسار له نوعforall c. a -> Either a c
. ربما تريد هنا. fail
يجب أن يكون النوعforall b. String -> Either a b
, ومع ذلك ، فإن الصحيح له نوعforall b. b -> Either a b
, ، حتى إذاb=String
الذي يجعلString -> Either a String
الذي لا يناسب.>>=
يجب أن يكون النوعEither a b -> (b -> Either a c) -> Either a c
ومع ذلكRight x >>= _ = Right x
يعيد دائمًا قيمة النوعEither a b
, ، ليسEither a c
.Left x >>= f = f x
لا يعمل لأن x له نوعa
, ، لكنf
لديه النوعb -> c
.
نصائح أخرى
ينبع معظم الارتباك من الحقيقة اليسرى واليمين للخلف. بالنظر إلى نوع العودة فقط ، فإن نوعه من monad typeclass هو كما يلي:
return :: (Monad m) => b -> m b
أنت تحاول تحديد مثيل ل m
= Either a
, ، لذلك يجب أن يكون للعودة نوع:
return :: b -> Either a b
أنت تحددها على أنها اليسار ، والتي لها نوع:
Left :: a -> Either a b
لاحظ كيف الجانب الأيسر من ->
يختلف.
لا تنتمي إلى StackOverflow