haskell / aeson

A fast Haskell JSON library
Other
1.26k stars 322 forks source link

Introduce Parser' #565

Open phadej opened 7 years ago

phadej commented 7 years ago

introduce new Parser' (name open to bikeshedding)

newtype Parser' a = Parser' {
      runParser' :: forall f r.
                   JSONPath
                 -> Value  -- different from primeless Parser
                 -> Failure f r
                 -> Success a f r
                 -> f r
    }

This will allow to modify FromJSON (in backward compatible way):

class FromJSON a where
    parseJSON :: Value -> Parser a
    parseJSON v = Parser $ \path f s -> runParser' parseJSON' path v f s   

    parseJSON' :: Parser' a
    parseJSON' = Parser' $ \path v f s -> runParser (parseJSON v) f s

    {-# MINIMAL parseJSON | parseJSON' #-}

Having Parser' will be a little more ergonomic, e.g. for

newtype X = X Y

instance FromJSON X where
    parseJSON' = X <$> parseJSON'

    -- instead of of old one
    parseJSON = fmap X . parseJSON
    -- or
    parseJSON = X <$$> parseJSON -- where (<$$>) = fmap . fmap

Prime version Parser' would require own variants of withObject

withObject' :: String -> (Object -> Parser a) -> Parser' a

OTOH, they aren't really required as

- parseJSON' = withObject' ...
+ parseJSON  = withObject  ...

Note:

-- bad
withObject' :: String
            -> (Object -> Parser' a) -- ^ we don't need prime here!
            -> Parser' a

In case this is bad idea, let's document why. Or is it already somewhere?

neongreen commented 7 years ago

There's http://hackage.haskell.org/package/aeson-value-parser-0.12.2/docs/Aeson-ValueParser.html, which implements this idea but goes further (it defines different monads for parsing objects, values, etc). I haven't used aeson-value-parser myself but I think it provides a much better API than Aeson.