在使用镜头时,我偶尔需要在光学链中进行一些基本的文本解析。在我处理的一个API中,有一个像这样的JSON字段:
"timespent": "0.25",
由于它被错误地编码为字符串而不是数字,我不能只执行典型的lens-aeson
解决方案:
v ^? key "timespent" . _Double -- this doesn't work
所以,我需要这个:
v ^? key "timespent" . _String . mystery
mystery
视神经需要将Text
转换为Double
。我知道mystery
可以输入如下:
mystery :: Prism' Text Double
我可以按如下方式构建:
mystery = prism' (pack . show) (readMaybe . unpack)
从技术上讲,这个函数可以有一个更加通用的类型签名,Read
和Show
约束,但这不是我的问题所在。我不喜欢的是Prism
对于我正在做的事情来说真的太强大了。大多数时候,我对解析感兴趣,但没有将它渲染回字符串。所以,我需要Traversal
或Fold
,但我不确定是哪一个,而且我不确定如何构建它们。当我查看^?
的类型签名以找到所需的最小光学元件时,我看到:
(^?) :: s -> Getting (First a) s a -> Maybe a
我可以理解这意味着什么,但不是很好。所以,为了使我的问题清楚,它是:
如果我有一个功能f :: Text -> Maybe a
,我该如何将其转换为Traversal
或Fold
?谢谢,如果有任何我可以澄清的话,请告诉我。
答案 0 :(得分:2)
我认为你想要的是Getter:
_Read :: Read a => Getter Text (Maybe a)
_Read f = contramap g . f . g where g = readMaybe . unpack
一般情况下,如果您有x :: a -> b
,那么\f -> contramap x . f . x
就是Getter a b
。
然后要从a
中获取Maybe a
值,请使用traverse
,因此合并后_Read . traverse
为Read a => Fold Text a
。