
On Tue, Nov 29, 2011 at 11:36 AM, Christian Maeder
Previously correct programs can now crash quite unpredictably without warnings!
Yeah, this bit the HTTP library too, but there was no way to address the infelicity without this happening.
My use case is (or better was) monadic code like:
typeCheck :: Monad m => ... -> m (...)
where I used the "Either String" Monad instance to extract the fail messages:
case typeCheck ... of Right ... -> ... Left ... -> ....
For this I now need another monad! Which one is recommended?
Cheers Christian
typeCheck :: ... -> Either String ... or even better, define a real error type, TypeError, and give typeCheck the return type Either TypeError ... which makes matching cases and reacting to problems much more straightforward, as well as up-front showing you the ways it can fail. You can then convert back to the generic version with 'either fail return' (or 'either (fail . show) return' in the TypeError case) but you probably won't need to most of the time, you'll just use the function as-is. Inside typeCheck, you just use Left instead of fail. If you use the do pattern-match failure, you isolate it in little Maybe blocks like the one I have above, with your own error message for each one. Something like: typeCheck :: AST -> Either TypeError Type typeCheck (Tuple xs) = do -- check the tuple has >= 2 elements check SyntaxError $ do [_,_] <- return (take 2 xs) return () -- type check them TupleType <$> mapM typeCheck xs check :: TypeError -> Maybe a -> Either TypeError a check err = maybe (Left err) Right Admittedly the 'return ()' is a little ugly, but the fact you're explicit about the error you're throwing makes up for it in my opinion. Notice that the line using mapM typeCheck xs wouldn't work in the past unless TypeError was an instance of Error; often there isn't a sensible way for it to be so.