来自readMaybe的Prism,Traversal或Fold

时间:2015-10-02 17:02:27

标签: json haskell lens

在使用镜头时,我偶尔需要在光学链中进行一些基本的文本解析。在我处理的一个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)

从技术上讲,这个函数可以有一个更加通用的类型签名,ReadShow约束,但这不是我的问题所在。我不喜欢的是Prism对于我正在做的事情来说真的太强大了。大多数时候,我对解析感兴趣,但没有将它渲染回字符串。所以,我需要TraversalFold,但我不确定是哪一个,而且我不确定如何构建它们。当我查看^?的类型签名以找到所需的最小光学元件时,我看到:

(^?) :: s -> Getting (First a) s a -> Maybe a

我可以理解这意味着什么,但不是很好。所以,为了使我的问题清楚,它是:

如果我有一个功能f :: Text -> Maybe a,我该如何将其转换为TraversalFold?谢谢,如果有任何我可以澄清的话,请告诉我。

1 个答案:

答案 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 . traverseRead a => Fold Text a