In working with lenses, I occasionally have the need for some basic text parsing in the chain of optics. In one API I'm dealing with, there is a JSON field like this:
"timespent": "0.25",
Since it is incorrectly encoded as a string instead of a number, I can't just do the typical lens-aeson solution:
v ^? key "timespent" . _Double -- this doesn't work
So, I need this instead:
v ^? key "timespent" . _String . mystery
where the mystery optic needs to turn Text into a Double. I know that mystery could be typed as follows:
mystery :: Prism' Text Double
And I could built this as follows:
mystery = prism' (pack . show) (readMaybe . unpack)
And technically, this function could have an even more general type signature with Read and Show constraints, but that's not really what my question is about. What I don't like is the Prism is really too strong for what I'm doing. Most of the time, I'm interested in parsing but not is rendering it back to a string. So, I need either a Traversal or a Fold but I'm not sure which one, and I'm not sure how to build them. When I look at the type signature of ^? to find the minimum optic required, I see:
(^?) :: s -> Getting (First a) s a -> Maybe a
I can sort of understand what this means but not very well. So, to make my question clear, it is:
If I have a function f :: Text -> Maybe a, how can I turn this into a Traversal or a Fold? Thanks, and let me know if there is anything I can clarify.
parseJSONso the string interpretation is integrated. The aeson parser type is monadic, so there's no difficulty producing a parse error from a higher stratum. Instead of thinking about., consider=<<. - dfeuer