
Hi list, tl;dr - I am using aeson and have an unusual JSON data structure to parse, so I have implemented the parseJSON function using the prisms and traversals in the lens-aeson package. Unfortunately, the only error message I ever get from my parser is "mempty". How can my parser give better error messages when using lens-aeson? Consider a need to implement parseJSON for the following type. data Row = Row [Text] Int Text The twist is that the values are in a JSON list, not an object. [["a","b","c"], 4, "a title"] The JSON above should be decoded to the following Haskell value. Row ["a", "b", "c"] 4 "a title" My first FromJSON instance was naive. instance FromJSON Row where parseJSON = withArray "Row" $ \ a -> case Vector.toList a of (x : y : z : []) -> Row <$> parseJSON x <*> parseJSON y <*> parseJSON z _ -> fail "Invalid Row." Then I decided that pattern matching a vector like that via an intermediate list was probably rookie stuff, so I tried lenses (this is my first attempt at lenses, btw). instance FromJSON Row where parseJSON v = Row <$> (v ^. nth 0 . to parseJSON) <*> (v ^. nth 1 . to parseJSON) <*> (v ^. nth 2 . to parseJSON) This looks like it works but now the only error message I get is "mempty". I think this is because the lens operators are folding with the Monoid Parser instance where mempty = fail "mempty". Can I continue to use lenses but produce better error messages? If so, how? The lens package haddocks baffle me. Any suggestions to improve my use of lenses are also welcome (e.g. the expression "to parseJSON" seems so useful that I thought it might be named in the lens-aeson package. But it isn't, so its absence makes me suspect that I'm using it incorrectly). Alternative, non-lens-based suggestions for de-constructing a Vector, pattern matching its elements, without too many intermediate lists or tuples are also welcome. Thanks in advance. -- Thomas Koster

Hi, Thomas!
I would come with implementation similar to this:
instance FromJSON Row where
parseJSON = withArray "Row" $ \ a ->
case Vector.length a of
3 ->
Row <$> parseJSON (a ! 0)
<*> parseJSON (a ! 1)
<*> parseJSON (a ! 2)
_ -> fail "Invalid Row."
Hope this helps.
On Fri, Jun 12, 2015 at 7:11 AM, Thomas Koster
Hi list,
tl;dr - I am using aeson and have an unusual JSON data structure to parse, so I have implemented the parseJSON function using the prisms and traversals in the lens-aeson package. Unfortunately, the only error message I ever get from my parser is "mempty". How can my parser give better error messages when using lens-aeson?
Consider a need to implement parseJSON for the following type.
data Row = Row [Text] Int Text
The twist is that the values are in a JSON list, not an object.
[["a","b","c"], 4, "a title"]
The JSON above should be decoded to the following Haskell value.
Row ["a", "b", "c"] 4 "a title"
My first FromJSON instance was naive.
instance FromJSON Row where parseJSON = withArray "Row" $ \ a -> case Vector.toList a of (x : y : z : []) -> Row <$> parseJSON x <*> parseJSON y <*> parseJSON z _ -> fail "Invalid Row."
Then I decided that pattern matching a vector like that via an intermediate list was probably rookie stuff, so I tried lenses (this is my first attempt at lenses, btw).
instance FromJSON Row where parseJSON v = Row <$> (v ^. nth 0 . to parseJSON) <*> (v ^. nth 1 . to parseJSON) <*> (v ^. nth 2 . to parseJSON)
This looks like it works but now the only error message I get is "mempty". I think this is because the lens operators are folding with the Monoid Parser instance where mempty = fail "mempty".
Can I continue to use lenses but produce better error messages? If so, how? The lens package haddocks baffle me.
Any suggestions to improve my use of lenses are also welcome (e.g. the expression "to parseJSON" seems so useful that I thought it might be named in the lens-aeson package. But it isn't, so its absence makes me suspect that I'm using it incorrectly).
Alternative, non-lens-based suggestions for de-constructing a Vector, pattern matching its elements, without too many intermediate lists or tuples are also welcome.
Thanks in advance.
-- Thomas Koster _______________________________________________ Beginners mailing list Beginners@haskell.org http://mail.haskell.org/cgi-bin/mailman/listinfo/beginners

Hi Alexey,
On Fri, Jun 12, 2015 at 7:11 AM, Thomas Koster
tl;dr - I am using aeson and have an unusual JSON data structure to parse, so I have implemented the parseJSON function using the prisms and traversals in the lens-aeson package. Unfortunately, the only error message I ever get from my parser is "mempty". How can my parser give better error messages when using lens-aeson?
instance FromJSON Row where parseJSON v = Row <$> (v ^. nth 0 . to parseJSON) <*> (v ^. nth 1 . to parseJSON) <*> (v ^. nth 2 . to parseJSON)
On 12 June 2015 at 16:28, Alexey Shmalko
I would come with implementation similar to this:
instance FromJSON Row where parseJSON = withArray "Row" $ \ a -> case Vector.length a of 3 -> Row <$> parseJSON (a ! 0) <*> parseJSON (a ! 1) <*> parseJSON (a ! 2) _ -> fail "Invalid Row."
Thanks for your response. I was so caught up in trying to do things "the Haskell, functional way", with pattern matching, that I totally overlooked the plain old (!) operator! I have decided that Row is not complex enough to need lens-aeson and will follow your recommendation. I might add this (.!) operator to my toolkit though, analogous to (.:), to remove the need for those "parseJSON"s. (.!) :: FromJSON a => Array -> Int -> Parser a I wonder why this is missing from aeson... I am still interested if an answer to the original question exists, should I need lens-aeson at some later time. Thanks, -- Thomas Koster
participants (2)
-
Alexey Shmalko
-
Thomas Koster