Gestion des erreurs dans Haskell avec un ou l'autre monade
-
09-09-2019 - |
Question
I ai une fonction qui vérifie si un type est un sous-type d'un autre type:
st :: Monad m => Map String Type -- ^type environment
-> Set (Type, Type) -- ^assumed subtypes
-> (Type, Type) -- ^we are checking if lhs <: rhs
-> m (Set (Type, Type))
Je veux faire le traitement des erreurs. J'ai la définition suivante:
instance Monad (Either String) where
return v = Right v
fail s = Left s
(Left s) >>= _ = Left s
(Right v) >>= f = f v
Parfois, je peux faire le traitement des erreurs en traitant le résultat de st que soit. Par exemple, la fonction suivante fonctionne, et moi obtient les messages qui résultent d'invoquer « échec » à l'intérieur de st:
isSubType env cs t1 t2 = result where
result = case st env (S.empty) (t1, t2) of
Left msg -> Left msg
Right rel -> Right ()
Maintenant, je suis à l'intérieur st et je veux appeler récursivement. Pour une raison quelconque, le code suivant, niché au fond de st:
let do_t1 rel t1 = case st env rel (t1, t2) of
Left msg -> fail $ printf "type %s in the union is not a subtype\
\ of the rhs, %s, because: %s" (renderType t1)
(renderType t2) (show msg)
Right rel -> return rel
Ne tapez pas vérifier, mais me donne l'erreur suivante:
No instance for (Monad (Either t))
arising from a use of `st'
at src/TypedJavaScript/Types.hs:386:24-42
Possible fix: add an instance declaration for (Monad (Either t))
Pourquoi est-ce le résultat de traitement de st que soit le travail à l'extérieur de « st », mais pas à l'intérieur? Comment puis-je changer mon code tel qu'il fonctionne à l'intérieur, aussi?
La solution
Je pense que le problème est que vous appelez show msg
où vous devez simplement utiliser msg
. Par conséquent, le compilateur ne peut pas en déduire que vous vouliez dire Either String
; tout ce qu'il sait est que vous avez Either t
où le Show t
de contrainte est satisfaite. Remplacement show msg
avec msg
doit corriger.