I have a function that checks whether a type is a subtype of another 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))
I want to do error handling. I have the following definition:
instance Monad (Either String) where
return v = Right v
fail s = Left s
(Left s) >>= _ = Left s
(Right v) >>= f = f v
Sometimes I can do error handling by treating the result of st as Either. For example, the following function works, and gets me the messages that result from invoking "fail" inside st:
isSubType env cs t1 t2 = result where
result = case st env (S.empty) (t1, t2) of
Left msg -> Left msg
Right rel -> Right ()
Now, I'm inside st and I want to recursively call it. For some reason, the following code, nested deep in 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
Does not type check, but gives me the following error:
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))
Why does treating the result of st as Either work outside of 'st' but not inside? How can I change my code such that it works inside, too?
I think the problem is that you call show msg
where you should just use msg
. As a result, the compiler can't deduce that you meant Either String
; all it knows is that you have Either t
where the constraint Show t
is satisfied. Replacing show msg
with msg
should fix it.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With