Haskell has the function parseTimeM, which replaces the deprecated parseTime function. I suppose the reason why the former is preferred over the latter is because it has better flexibility in reporting parse errors. Instead of a Maybe, it can call fail on the enclosing monad.
So I tried it. First, the deprecated function:
> parseTime defaultTimeLocale "%Y" "2015" :: Maybe UTCTime
Just 2015-01-01 00:00:00 UTC
> parseTime defaultTimeLocale "%Y" "201x" :: Maybe UTCTime
Nothing
Great. As expected. Then, the Identity monad:
> runIdentity $ parseTimeM False defaultTimeLocale "%Y" "2015" :: UTCTime
2015-01-01 00:00:00 UTC
> runIdentity $ parseTimeM False defaultTimeLocale "%Y" "201x" :: UTCTime
*** Exception: parseTimeM: no parse of "201x"
Also expected, since the Identity monad doesn't have an elegant failure mode. But, I expected something different with the Except monad, the purpose of which is to gracefully catch errors.
> runExcept $ parseTimeM False defaultTimeLocale "%Y" "2015" :: Either () UTCTime
Right 2015-01-01 00:00:00 UTC
> runExcept $ parseTimeM False defaultTimeLocale "%Y" "201x" :: Either () UTCTime
*** Exception: parseTimeM: no parse of "201y"
Why is the exception being thrown here? Shouldn't it return Left () ? How do I parse a time like I think it should, which is to gracefully return an error if the string to be parsed is poorly formatted?
Except is part of the mtl, which is a monad transformer library. The usual style with transformers is to define the transformer for some behavior (ExceptT in this case) and express the base version as a type synonym:
type Except e = ExceptT e Identity
So you are probably getting an exception because the fail for Except has to go through the Identity monad at the bottom of its little monad transformer stack.
With Except e specifically, how would you implement fail for an arbitrary type e? Since we don't know anything at all about e, we can't just conjure up a value of e given a string, so fail would have to give you an exception or loop forever.
All this is a pretty good argument against the parseTimeM style of relying on fail in the Monad class.
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