From JSON to sum type

For a while I’ve been planning to take full ownership of the JSON serialisation and parsing in cblrepo. The recent inclusion of instances of ToJSON and FromJSON for Version pushed me to take the first step by writing my own instances for all external types.

When doing this I noticed that all examples in the aeson docs use a product

whereas I had to deal with quite a few sums, e.g. VersionRange. At first I struggled a little with how to write an instance of FromJSON. After quite a bit of thinking I came up with the following, which I think is fairly nice, but I’d really like to hear what others think about it. Maybe I’ve just missed a much simpler way of implementing parseJSON:

Any and all comments and suggestions are more than welcome!

David Turner


f >>= return . g

The same as

fmap g f


Or something like that anyway?

Magnus Therning

@David, yes, f >>= return . g is the same as fmap g f. However, since in this case g is of the form fmap h it would end up looking like

and then I find f >>= return . fmap h to be a bit easier to read and understand.

David Turner

Actually, a couple of other ideas too. First, why not just use .:? Parsers themselves are instances of Alternative so you can use <|> to combine two parsers where if the first fails then the second is tried.

Secondly, I’d recommend not naming all the intermediate results and then combining them at the bottom. Too many times have I come across a bug where there was one missing in the final list! I can’t remember off the top of my head whether there’s a choice operator here as there is in e.g. attoprasec, but if there isn’t there should be!

David Turner

So here’s how I would write this function:

Никита Тимофеев

Perhaps it would be better to use a transformer MaybeT?

Leave a comment