You're doing a lot of work you don't need to do. First you check if you're at the end of the data and return Nothing
if that doesn't work out. That's just not necessary, because if you're at the end, any parser that requires content will fail, and using maybeResult
will turn that failure into Nothing
.
The only time your parser fails is with the case where the input has data which doesn't start with the character :
, the rest of the time it succeeds, even if that's by returning Nothing
.
The only actual parsing going on is checking for :
then using A.json
. I think you're trying to write the whole program inside one parser, whereas you should just do the parsing on its own then call that as necessary. There's no need to check for end of data, or to make sure you get the whole content - that's all built in for free in a parser. Once you get rid of all that unnecessary checking, you get
payload :: Parser A.Value
payload = char ':' *> A.json
If you want to you can use that as maybeResult $ parse payload input
to get a Maybe A.Value
that's not additionally wrapped in a Parser
. If you don't apply maybeResult
, you can pattern match on the Result returned to deal separately with Fail
ure, Partial
success and Success
.
Edit: OK, clearer now, thanks:
- (If there's a colon followed by invalid json, fail)
- If there's a colon followed by valid json, succeed, wrapping it in Just
- If there's just end of input, succeed, returning Nothing
So we get:
maybePayload :: Parser (Maybe A.Value)
maybePayload = char ':' *> (Just <$> A.json)
<|> (Nothing <$ endOfInput)
I've used <$>
and <$
from Control.Applicative
, or if you prefer, from Data.Functor
.
<$>
is an infix version of fmap
, so Just <$> A.json
does A.json
and wraps any output in Just
.
<$
is fmap.const
so replaces the ()
from endOfInput
with Nothing
.