我对镜头的魔力很新,所以我遇到了一些麻烦.
参考:https://www.fpcomplete.com/user/tel/lens-aeson-traversals-prisms
可以通过以下方式遍历JSON对象:
val ^? nth 0 . key "someObject" . key "version" . nth 2
对于类似于的JSON对象:
"[{\"someObject\": {\"version\": [1, 0, 3]}}]"
Maybe Monad在整个过程中使用,所以如果任何"访问者"失败,我会得到一个Nothing
.
我也想传播失败,以便我知道访问者失败了.
我能想到的唯一方法就是传递一组访问器,按顺序应用它们,并在任何失败点返回错误.像这样的东西:
import Data.Aeson import Data.Text import Data.Vector ((!?)) import qualified Data.HashMap.Strict as HM data MyAccessor = Nth Int | Key Text withFailure :: Value -> [MyAccessor] -> Either String Value withFailure val [] = Right val withFailure val (x:xs) = case x of Nth i -> case val of (Array val') -> case (val' !? i) of Just e -> withFailure e xs _ -> Left $ "Could not get index " ++ (show i) _ -> Left $ "Expected JSON array for index " ++ (show i) Key k -> case val of (Object val') -> case (HM.lookup k val') of Just e -> withFailure e xs _ -> Left $ "Could not get key " ++ (unpack k) _ -> Left $ "Expected JSON object for key " ++ (unpack k)
所以这个:
-- val = [[1,0,3], {"name" : "value"}] > withFailure val [Nth 1, Key "name", Key "hello"] Left "Expected JSON object for key hello" > withFailure val [Nth 1, Key "name"] Right (String "value")
有更优雅的方式吗?制作一个Either-ish monad供镜头使用,结果就像是什么withFailure
?