I'm not sure if I'm barking up the wrong tree here, but I have an Aeson FromJSON
definition that looks rather bulky and I was wondering if it could be turned into something more concise. I want to short-circuit the parsing of the entire object if the nested parsing of the URI fails.
data Link = Link { link :: URI
, tags :: [String]
} deriving (Show, Typeable, Eq)
instance FromJSON Link where
parseJSON :: Value -> Parser Link
parseJSON (Object o) = do
linkStr <- o .: "link"
tags' <- o .: "tags"
case parseURI linkStr of
Just l -> return $ Link l tags'
Nothing -> mzero
parseJSON _ = mzero
The type of parseURI
is parseURI :: String -> Maybe URI
and both Maybe
and Parser
have MonadPlus
instances. Is there a way to compose the two directly and remove the ugly case statement at the end?
Applicative parsers are usually more concise and you can compose the result of parseURI
using maybe mzero return
which converts a Nothing
into an mzero
.
instance FromJSON Link where
parseJSON :: Value -> Parser Link
parseJSON (Object o) = Link
<$> (maybe mzero return . parseURI =<< o .: "link")
<*> o .: "tags"
parseJSON _ = mzero