Mam funkcję, która sprawdza, czy dany typ jest podtypem innego typu:Obsługa błędów w Haskell albo monady
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))
chcę zrobić obsługę błędów. Mam następującą definicję:
instance Monad (Either String) where
return v = Right v
fail s = Left s
(Left s) >>= _ = Left s
(Right v) >>= f = f v
Czasami mogę zrobić obsługę błędów traktując wynik st jako Either. Na przykład, poniższa funkcja działa i pobiera mi wiadomości, które wynikają z wywoływania „fail” wewnątrz St:
isSubType env cs t1 t2 = result where
result = case st env (S.empty) (t1, t2) of
Left msg -> Left msg
Right rel -> Right()
Teraz jestem wewnątrz st i chcę rekursywnie nazwać. Z jakiegoś powodu, poniższy kod, zagnieżdżona głęboko w 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
Nie typ kontroli, ale daje mi następujący błąd:
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))
Dlaczego traktując wynik st albo jako praca poza "st", ale nie w środku? Jak mogę zmienić mój kod tak, aby działał w środku?
Wygląda na to, że ponownie wdrażasz [Control.Monad.Error] (http://www.haskell.org/ghc/docs/latest/html/libraries/mtl/Control-Monad-Error.html)? – ephemient